静态导入
Import 语句可以导入一个类或某个包中的所有类
Import static语句导入一个类中的某个静态方法或所有静态方法
可变参数:一个方法接受的参数个数不固定
1. 只能出现在参数列表的最后
2. ...位于变量类型和变量名之间
3. 调用可变参数方法,编译器隐含创建一个数组,方法体中以数组形式访问可变参数
增强for循环
for(type 变量名:集合变量名){…}
迭代变量必须在()中定义
集合变量可以是数组或实现了Iterable接口的集合类
Eg. for(int arg :args){
sum+=arg ;
}
基本数据类型的自动装箱与拆箱
装箱:Integer num1=12;
拆箱:System.out.println(num1+12);
Integer num1=12;
Integer num2=12;
Integer num1=129;
Integer num2=129;
设计模式:享元模式
枚举
让某个类型的变量的取值只能为若干个固定之中的一个
1..私有的构造方法
2.每个元素分别用一个公有的静态成员变量表示
3..可以由若干个公有方法或抽象方法。
用普通类模拟枚举的实现原理
枚举的基本应用
举例:定义一个weekday的枚举
扩展:枚举类的values,value Of,name,toString,ordinal等方法
总结:枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象,例如可以调用WeekDay.SUN.getClass().getName和WeekDay.class.getName()
枚举就相当于一个类,其中也可以定义构造方法,成员变量,普通方法和抽象方法。
枚举元素必须位于枚举体重的最开始部分,枚举元素列表的后要有分号与其他成员分隔。把枚举中的成员方法或变量等放在枚举元素的前面,编译器报告错误。
带构造方法的枚举:
构造方法必须定义成私有的
如果有多个构造方法,该如何选择哪个构造方法?
枚举元素MON和MON()的效果一样,都是调用默认的构造方法。
带方法的枚举
定义枚举的TrafficLamp
实现普通的next()方法
实现抽象的next()方法:每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似的内部类的方式进行定义。
枚举只有一个成员时,就可以作为一种单例的实现方式。
反射的基石—>Class类
Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class
Class类描述了类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表。
如何得到各个字节码对应的实例对象(Class类型)
类名:class
对象:getClass()
Class.forName(“类名”)
九个预定义Class实例对象:
参看Class.isPrimitive方法的帮助
Int.class==Integer.TYPE
数组类型的Class实例对象
Class.isArray()
只要是在源程序中出现的类型,都有各自的Class实例对象
反射
反射就是把java类中的各种成分映射成相应的java类。
例如:一个java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的javva类来表示
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,。。。
Constructor类
Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法:
Constructor constructors[]=Class.forName(“java.lang.String”).getConstructors();
得到某一个构造方法:
Constructor constructors[]=Class.forName(“java.lang.String”).getConstructors(StringBuffer.class);
创建实例对象:
通常方式:String str=new String(new StringBuffer(‘abc’));
反射方式:String str=(String)constructor.newInstance(new StringBuffer(“abc”));
//调用获得的方法要用到上面相同类型的实例对象
Class.newInstance()方法:
例:String obj=(String)Class.forName(“java.lang.String”).newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部用到了缓存机制来保存默认构造方法的实例对象。
Field类
Field类代表某个类中的一个成员变量
Method类
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对象对应的一个静态方法
用反射方式执行某个类中的main方法
数组的反射
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
基本类型的一维数组可以被当做Object类型使用,不能当作Object[]类型使用,非基本类型的一维数组,既可以当做Object类型使用,也可以当做Object[]类型使用
Arrays.asList()方法处理int[]和String[]时的差异
Array工具类用于完成对数组的反射操作
反射的作用:实现框架功能
了解javaBean
javaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个javaBean中,这种javaBean的实例对象称之为值对象,(VO:Value Object)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,javaBean的属性是根据其中的setter(),getter()方法来确定,而不是根据其中的成员变量
一个类被当做javaBean使用时,javaBean的属性是根据方法名推断出来的,根本看不到java类内部的成员变量。
当做javaBean好处:
JDK提供了对javaBean进行操作的一些API----内省API
Beanutils工具包
了解注入及java提供的几个基本注解
@SuppressWarnings
@Deprecated:直接在刚才的类中增加一个方法,并加上@Deprecated,标注,在另外一个类中调用这个方法。
@Override
注解相当于一种标记,java编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无标记,去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
看java.lang包,可看到JDK中提供的最基本的annotation。
自定义注解及应用
定义一个最简单的注解:public @interface MyAnnotation{}
把它加在某个类上:@MyAnnotation
public class Annotation Test{}
用反射进行测试Annotation Test的定义上是否有@MyAnnotation
根据发射测试的问题:引出@Retetion 元注解的讲解,其三种取值:
RetetionPolicy.SOURCE,RetetionPolicy.CLASS,RetetionPolicy.RUNTIME分别对应:
java源文件------------àclass文件------------à内存中的字节码
@Target元注解
Target的默认值为任何元素,用数组方式设置(ElementType.METHOD,ElementType.TYPE)]
为注解增加基本属性
定义基本类型的属性和应用属性
在注解类中增加String color()
@MyAnnotation(color=”red”)
用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应地方法
MyAnnotation a=(MyAnnotation)Annotation Test.class.getAnnotation(MyAnnotation.class)
System.out.println(a.color())
为属性指定缺省值:
String color() default “yellow”
为注解增加高级属性
数组类型的属性
Int[] arrayAttr() default {1,2,3}
@MyAnnotation(arrayAttr={2,3,4})
枚举类型的属性
EnumTest.TrafficLamp lamp()
@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
注解类型的属性:
泛型
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会除去类型信息,是程序运行效率不受影响,对参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。
参数化类型与原始类型的兼容性:
参数化类型可以引用一个原始类型的对象,编译报告警告
原始类型可以引用一个参数化类型的对象,编译报告警告
参数化类型不考虑类型参数的继承关系
在创建数组实例时,数组的元素不能使用参数化的类型
泛型中的通配符
限定通配符的上边界:
Vector<? Extends Number> x=new Vector<Integer>()
限定通配符的下边界:
Vector<? Super Integer> x = new Vector<Number>()
提示:限定通配符总是包括自己。
定义泛型地方法:
用于放置泛型的类型参数的尖括号应出现在方法的其他所有修饰符之后和方法的返回类型之前,也就是紧邻返回值之前。类型参数通常用单个大写字母表示
只有引用类型才能作为泛型方法的实际参数
除了在应用泛型时可以使用extends限定符,在定义泛型时也可以使用extends限定符
普通方法,构造方法和静态方法中都可以使用泛型,编译器也不允许创建类型变量的数组
也可以用类型变量表示异常,成为参数化的异常,可以用于方法的throws列表中,但是不能用于catch字句中。
在泛型中可以同时有多个类型参数,在定义他们的尖括号中用逗号分。
定义泛型类型
如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这个时候就要采用泛型类型的方式进行定义,也几乎是类级别的泛型。
类级别的泛型是根据引用该类名时指定的类型信息来参数化类型变量的。
注意:在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。
当一个变量被声明为泛型时,只能被实例变量和方法调用,而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。
类加载器
什么是类加载器,类加载器的作用
Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责家在特定位置的类:BootStrap,ExtClassLoader,AppClassLoader
类加载器也是java类,因为其他事java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap
Java虚拟机中所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载。
类加载器的委托机制
当java虚拟机要加载一个类时,到底派出哪个类加载器去加载?
首先当前线程的类加载器去加载线程中的第一个类
如果类A中引用了类B,java虚拟机将使用加载类A的类加载器来加载类B
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类
每个类加载器加载类时,又先委托给其上级类加载器
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法
编写自己的类加载器
自定义的类加载器必须继承ClassLoader
loadClass方法与findClass方法
defineClass方法
动态代理技术
Jvm可以在运行期动态生成出类的字节码----动态代理
Jvm生成的动态类必须事先一个或多个接口,所以jvm生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理。所以如果要为一个没有实现接口的类生成动态代理类,可以用CGLIB库
代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码
在调用目标方法之前,之后,前后,在处理目标方法异常的catch块中
让动态生成的类成为目标类的代理
分析动态代理的工作原理
怎样将目标类穿进去?
直接在InvocationHandler实现类中创建目标类的实例对象,可以看运行效果和加入日志代码。
为InvocationHandler实现类注入目标类的实例对象,不能采用匿名内部类的形式
让匿名的InvocationHandler实现类访问外面方法中的目标类实例对象的final类型的引用变量
实现AOP功能的封装与配置
工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换,其getBean方法恩聚餐书字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFacoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。