黑马程序员------张孝祥老师视频笔记------高新技术

来源:互联网 发布:网络侦查学专业代码 编辑:程序博客网 时间:2024/06/04 20:34

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

一. eclipse开发工具

什么是IDE?

在项目开发的过程中,如果一个项目中包括多个Java源文件,编程人员需要精心维护这些源文件之间、以及源文件与其它文件的目录关系,需要逐一编译这些源文件,需要手工启动运行编译后的结果,这时很麻烦的。

IDE开发工具都支持使用工程化方式管理一个项目的程序开发过程,一般来说一个相对独立的项目就是一个工程,一个项目中涉及的多个java文件,资源文件等用一个工程进行管理。如果将一个程序的所有源文件用一个工程来组织,开发工具能对所有源文件集中管理,记住每个源文件的位置和相互关系。工程中有哪几个源文件、启动类是哪个、启动参数设置等配置信息在工程中都记录。

常用的Java开发使用IDE工具除了Eclipse(MyEclipse)外还有NetBeans、JBuilder等。

Myeclipse的核心就是eclipse,只不过Myeclipse在此基础上增加了许多的插件,使用起来更加的方便。eclipse实际上就是使用java语言开发的,所以eclipse是基于java运行的。

 

Workspace与project的关系是什么?

一个workspace可以包含多个project,一个workspace保留了eclipse的一套环境选项的配置。如果要为eclispe再配置一套环境选项,可以再创建一个workspace。对Workspace的修改会影响到它所有的全部工程的设置。高版本的java可以运行低版本的javac编译的程序,低版本的java不能运行高版本的javac编译的程序。

 

MyEclipse中常用的快捷键:

Alt+/:代码提示

Ctrl+/:注释/取消注释

Ctrl+D:删除光标所在行

Ctrl+K:将光标停留在变量上,按Ctrl+K键可以查找到下一个同样的变量

Shift+Ctrl+K:和Ctrl+K查找的方向相反

Shift+Ctrl+F:代码格式化。如果选择了代码,仅对所选代码格式化

Shift+Ctrl+O:快速地导入import

Shift+Ctrl+X:将所选字符转为大写

Shift+Ctrl+Y:将所选字符转为小写

Ctrl+M:快速对当前视图最大化

Ctrl+O:在代码中打开类似大纲视图的小窗口

Ctrl+单击:可以跟踪方法和类的源码

Alt+左右方向键:跳到前一次/后一次的编辑位置。

Ctrl+鼠标停留:可以显示类和方法的源码

双击左括号(小括号、中括号、大括号),将选择括号内的所有内容。

Ctrl+1:光标停在某变量上,按Ctrl+1键,可以提供快速重构方案。选中若干行,按Ctrl+1键可将此段代码放入for、while、if、do或try等代码块中。

F3:打开声明该引用的文件

F4:打开类型层次结构

F5:单步跳入

F6:单步跳过

F7:单步跳出

F8:继续,如果后面没有断点,程序将运行完

Ctrl+H:打开搜索窗口

Ctrl+Shift+S:保存全部

Alt+Left:回退一步

Alt+Right:前跳一步

Ctrl+Shift+T:打开类型

Ctrl+Shift+R:打开资源

Ctrl+Q:回到最后一次编辑的地方

Ctrl+Shift+G: 在workspace中搜索引用

Ctrl+Alt+Down: 复制高亮显示的一行或多行

Alt+Up(Down):将一行或者多行向上或者向下移动

 

二. java5的一些简单新特性

1.静态导入

静态导入可以导入静态方法,这样就不必写类名而可以直接调用静态方法了。

import static 包名.类名.静态方法名;

import static 包名.类名.*;

静态导入是jdk1.5的新特性,如果将javac设置为了Java5以下,那么静态导入等jdk1.5的特性都会报告错误。

 

2.可变参数

修饰符返回值 方法名(变量类型 变量1, 变量类型 变量2, 变量类型… 变量名3)

可变参数的特点:

①只能出现在参数列表的最后。

②...位于变量类型和变量名之间,前后有无空格都可以。

③调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。

 

3.增强for循环

for ( type 变量名:集合变量名 )  { … }

迭代变量必须在( )中定义!

集合变量可以是数组或实现了Iterable接口的集合类。

 

4.基本数据类型的自动拆箱与装箱

在Java中,一切都是对象,所以将基本数据类型包装成了对象。

在jdk1.5以后,包装对象引用可以和对应基本数据类型变量混用,因为会自动装箱拆箱。

享元设计模式flyweight

如果有很多很小的对象,并且他们有相同的东西,那就可以把他们作为一个对象。如果还有很多不同的东西,那就可以作为外部的东西,作为参数传入。

 

5.枚举

枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。

à用普通类实现枚举功能

①私有的构造方法。

②每个元素分别用一个公有的静态成员变量表示。

③可以有若干公有方法或抽象方法。

总结:

枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象。

最后一个枚举元素后面可以加分号,也可以不加分号。

枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法。

枚举元素必须位于枚举体中的最开始部分,枚举元素列表的最后要有分号与其他成员分隔。把枚举中的成员方法或变量等放在枚举元素的前面,编译器会报告错误。

à实现带有构造方法的枚举

构造方法必须定义成私有的,如果有多个构造方法,将根据枚举元素创建时所带的参数决定选择哪个构造方法创建对象。

枚举元素MON和MON()的效果一样,都是调用默认的构造方法。

枚举只有一个成员时,就可以作为一种单例的实现方式。

 

三. 反射的深入讲解

1.反射的基础------Class类

学习反射,首先要明白Class类。

Class类代表Java类,它的各个实例对象对应各个类在内存中的字节码。

一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,这个类型就是Class。

Class类描述了类的名字,类的访问属性,类所属于的包名,字段名称的列表、方法名称的列表等等信息。

à如何得到各个字节码对应的实例对象(Class类型)

①类名.class,例如,System.class。

②对象.getClass(),例如,new Date().getClass()。

③Class.forName("类名"),例如,Class.forName("java.util.Date");。

à九个预定义Class实例对象(八大原始类型+void):

à注意:

①Int.class == Integer.TYPE。

②数组类型的Class实例对象Class.isArray()为true。

③反射并不是Java5的新特性。

④只要是在源程序中出现的类型,都有各自的Class实例对象。

 

2.反射的概念

反射就是把Java类中的各种成分映射成相应的java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。

一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象。

 

3.构造方法的反射

Constructor类代表某个类中的一个构造方法。Constructor对象代表一个构造方法,Constructor对象上会有的方法有:得到方法名字,得到所属于的类,产生实例对象。

à得到某个类所有的构造方法:

Constructor[] constructors=Class.forName("java.lang.String").getConstructors();

à得到某一个构造方法:

 Constructorconstructor =Class.forName("java.lang.String").getConstructor(StringBuffer.class);

注意:

一个类有多个构造方法,根据参数的个数和类型可以区分清楚得到的是其中的哪个方法,例如,Class.getMethod(name,Class... args)中的args参数就代表所要获取的那个方法的各个参数的类型的列表。参数类型用Class实例对象表示。

à创建实例对象:

通常方式:String str = new String(new StringBuffer("abc"));

反射方式: String str = (String)Constructor.newInstance(newStringBuffer("abc"));

àClass.newInstance()方法:

String obj =(String)Class.forName("java.lang.String").newInstance();

该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

 

4.成员变量的反射

Field类代表某个类中的一个成员变量。字段fieldX代表的是x的定义,而不是具体的x变量。

 

5.成员方法的反射

·Method类代表某个类中的一个成员方法。

得到类中的某一个方法:

Method charAt =Class.forName("java.lang.String").getMethod("charAt",int.class);

调用方法:

 通常方式:System.out.println(str.charAt(1));

 反射方式:System.out.println(charAt.invoke(str,1));

注意:

如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!

àjdk1.4和jdk1.5的invoke方法的区别:

Jdk1.5:public Objectinvoke(Object obj,Object... args)

Jdk1.4:public Objectinvoke(Object obj,Object[] args)

即按jdk1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数。所以,调用charAt方法的代码也可以用Jdk1.4改写为 charAt.invoke("str", new Object[]{1})形式。

 

6.对接收数组参数的成员方法进行反射

Class类的getName方法返回值中[表示数组的深度,[表示一维数组,[[表示二维数组。剩下的内容则表示数组类型,例如I表示int类型。

注意:

当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。

 

四. JavaBean内省

JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。

JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。如果方法名为setId,中文意思即为设置id,至于你把它存到哪个变量上,则不用管。如果方法名为getId,中文意思即为获取id,至于你从哪个变量上取,也不用管。去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。

总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。

一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处,我们才会去了解和应用JavaBean!

à好处如下:

①在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,别人都这么用和要求这么做,那你就没什么挑选的余地!

②JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。如果要你自己去通过getX方法来访问私有的x,怎么做,有一定难度吧?用内省这套api操作JavaBean比用普通类的方式更方便。

 

五. java5的注解

@SuppressWarnings("deprecation")

在main方法上添加一个注解:@SuppressWarnings("deprecation"),此注解的作用就是告诉编译器,虽然我用的方法过时了,但是我还是坚持要用,你就不要再提示了。

@Deprecated

有时候我们写的方法被别人调用了,但是如果这个方法有一些bug需要修改,可是如果我们修改了又会影响以前已经调用这个方法的程序。这时候我们可以把这个方法设置为过时,然后重新写一个方法,这时候就需要用到@Deprecated注解。

@Override

有时候我们写的某些方法需要覆盖父类的方法,但是可能方法名或者参数会出现不小心写错的情况。这时候就可以为这个方法打上@Override注解,如果有任何差错,eclipse就会报错。

例如equals方法的参数为Object obj,但是经常会被写错,这时候就可以通过@Override注解避免这种情况。

à注意:

①注解是Java1.5的新特性。

②一个注解就是一个类,使用注解,就相当于创建了一个对象。

③注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记。以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

④看java.lang包,可看到JDK中提供的最基本的annotation。

 

六. java5的泛型

Jdk 1.5的集合类希望在定义集合时,明确表示要向集合中装哪种类型的数据,无法装入指定类型以外的数据,否则在编译的时候就会报错。没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。使用泛型集合,可以将一个集合中的元素限定为一个特定类型,集合中只能存储同一个类型的对象,这样更安全;并且当从集合获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,更方便。

泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入。但是,编译器编译带类型说明的集合时会去除掉“类型”信息,目的就是使程序运行效率不受影响。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。

Java中的泛型类型(或者泛型)类似于 C++ 中的模板。但是这种相似性仅限于表面,Java 语言中的泛型基本上完全是在编译器中实现,用于编译器执行类型检查和类型推断,然后生成普通的非泛型的字节码,这种实现技术称为擦除(erasure)(编译器使用泛型类型信息保证类型安全,然后在生成字节码之前将其清除)。这是因为扩展虚拟机指令集来支持泛型被认为是无法接受的,这会为 Java 厂商升级其 JVM 造成难以逾越的障碍。所以,java的泛型采用了可以完全在编译器中实现的擦除方法。

只有引用类型才能作为泛型方法的实际参数,除了在应用泛型时可以使用extends限定符,在定义泛型时也可以使用extends限定符,并且可以用&来指定多个边界

普通方法、构造方法和静态方法中都可以使用泛型。也可以用类型变量表示异常,称为参数化的异常,可以用于方法的throws列表中,但是不能用于catch子句中。

类级别的泛型是根据引用该类名时指定的类型信息来参数化类型变量的。

在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。

当一个变量被声明为泛型时,只能被实例变量、方法和内部类调用,而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。

 

七. 类加载器的深入讲解与应用

àJava虚拟机中可以安装多个类加载器,系统默认有三个主要的类加载器,每个类加载器负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader。

类加载器也是Java类,因此java类的类加载器本身也要被其他的类加载器加载,显然必须有第一个类加载器不是java类,它就是BootStrap类加载器。

注意:

JVM内核启动的时候,BootStrap就已经被加载了,它是内嵌在JVM内核中的,是用C++语言编写的二进制代码,因此不需要其他类加载器加载。

Java虚拟机中的所有类装载器采用了具有父子关系的树形结构进行组织。

à类加载器的委托机制

当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?

 首先当前线程的类加载器去加载线程中的第一个类。

 如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。

 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。

每个类加载器加载类时,又先委托给其上级类加载器。

 当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?

 

八. 动态代理技术的深入讲解

à代理的概念与作用

要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、事务管理、等等,如何做?

编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。

如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易。

注意:安全,事务,日志等功能要贯穿到好多个模块中,所以,它们就是交叉业务。

重要原则:不要把供货商暴露给你的客户。

à动态代理技术

要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事情!写成百上千个代理类,是不是太累!

JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。

JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。

CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。

代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:在调用目标方法之前、在调用目标方法之后、在调用目标方法前后、在处理目标方法异常的catch块中

StringBuilder与StringBuffer的区别?

StringBuffer是线程安全的,StringBuilder是线程不安全的。

StringBuilder在单线程的时候使用,StringBuffer则是在多线程的时候使用。

因此StringBuilder比StringBuffer效率高一些。

让jvm创建动态类及其实例对象,需要给它提供哪些信息?

三个方面:

①生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知;

②产生的类字节码必须有个一个关联的类加载器对象;

③生成的类中的方法的代码是怎样的,也得由我们提供。把我们的代码写在一个约定好了接口对象的方法中,把对象传给它,它调用我的方法,即相当于插入了我的代码。

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

0 0
原创粉丝点击