可变参数,只能放在后面
方法的重写Override和重载Overload是Java多态性的不同表现。
重写Override是父类与子类之间多态性的一种表现,如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Override)。子类的对
象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了;
重载Overload是一个类中多态性的一种表现。。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的
重载(Overload)。
注意:
1. 重写方法唯一可变的是访问修饰,且重写方法级别只能低于父类方法。
如:父类方法protected子类方法public
2. Overload的方法是可以改变返回值的类型和访问级别。重载必须是参数不同!
享元模式:Integer
当很多小的很相同属性时,重复的使用时,缓存起来,封装成一个对象,当再次使用时直接拿来用。
StringBuffer 和StringBuilder的区别:
1. 在应用上基本一样,都是动态的往字符串上添加内容。
2. 单线程的情况下StringBuilder的效率要高一点。如果在多线程的情况下要用StringBuffer。
javaBean的内省:
例子:告诉你对象中有个属性的名称,得到属性对应的值
ReflectPoint pt=new ReflectPoint(3,5);
String propertyName="x";//ReflectPoint类中有个属性名为x
//常用是去掉get和set后的就是它的属性名:getAge 的属性名是age,如果第二个字母是小的,则把第一个字母变成小的
PropertyDescriptor pd=new PropertyDescriptor(propertyName,pt.getClass());
method method=pd.getReadMethod();//只读方法
Object retValue=method.invoke(pt);//运行方法
Method methodSetX=pd.getWriteMethod();//设值
methodSetX.invoke(pt,7);//传对象,设的值
注解(Annotation)
生命周期:
RetentionPolicy.RUNTIME:字节码阶段
RetentionPolicy.CLASS:class文件中
RetentionPolicy.SOURCE:java源文件中
@Target:注解作用于类的哪个成分,值为ElementType枚举值
Target的默认值为任何元素。
为注解增加属性:
public@interface MyAnnotation{
String color();//为注解增加了color属性,使用时@MyAnnotation(color=”red”)
String value();//特殊属性,在使用时可以不用写属性名。
}
可以为属性添加默认值:Stringcolor() default “red”;
数组属性使用方式:属性名={value1,value2};
注解类型的属性:假设有元注解类型@MetaAnnotation
MetaAnnotationannotationAttr() default @ MetaAnnotation(“值”);//设置默认值方式。
泛型
泛型是提供给javac编译器使用的。可以限定结合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信
息,是程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,
只要能跳过编译器,就可以往反省集合中加入其它类型的数据。
ArrayList<Integer>a = new ArrayList();
ArrayList<String> b = newArrayList();
System.out.println(a.getClass()== b.getClass());//同一份字节码
System.out.println(a.getClass());//返回java.util.ArrayList
参数化类型不考虑类型参数的继承关系:
Vector<Object>v = new Vector<String>();//错误
Vector<String>v = new Vector<Object>();//也错误
这两个类型是没有转化关系的类型。改成如下即可:
Vector v = newVector<String>();
Vector<Object>v2 = v;
泛型的通配符扩展应用
“?”表示任意类型。
使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。
泛型方法定义:
public static<T> T add(T x, T y){
}
用于放置泛型的类型参数的尖括号应出现在方法的其他所有修饰符之后和在方法的返回值类型之前,也就是紧邻返回值之前。按照惯例,类型参数通常
用单个大写字母表示。
只有引用类型才能作为泛型方法的实际参数。
除了在应用泛型时可以使用extends限定符,在定义泛型时也可以使用extends限定符。
普通方法,构造方法,和静态方法中都可以使用泛型。编译器也不允许创建类型变量的数组。
也可以用类型变量表示异常,成为参数化的异常,可以用于方法的throws列表中。但是不能catch子句中。
在泛型中可以同时有多个类型参数。在定义他们的尖括号中用逗号分隔。
泛型方法练习
强制转化类型:
public static <T> T autoConvert(Object obj){
return (T)obj;
}
调用:Object obj= “ddd”;
String x = autoConvert(obj);
当一个类型变量用来表达两个参数之间后者参数和返回值之间的关系时,即同一个类型变量在方法签名的两处都被使用,或者类型变量在方法体代码中
也被使用而不是仅在签名的时候使用,才需要使用泛型方法。
注意:
1. 在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。
2. 当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的
类所共享的,所以静态成员不应该有类级别的类型参数。
类加载器
Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:
BootStrap<—ExtClassLoader<—AppClassLoader//父子关系
BootStrap不是java类,System类就是由这个类加载器加载的。
BootStrap:加载JRE/lib/rt.jar
ExtClassLoader:加载JRE/lib/ext/*.jar
AppClassLoader:加载CLASSPATH指定的所有jar或目录
类加载器的委托机制
当java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
1. 首先当前线程的类加载器去加载线程中的第一个类。
2. 如果类A中引用了类B,java虚拟机将使用加载类A的加载器来加载类B
3. 还可以直接调用ClassLoader.loadClass()方法来制定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上一级类加载器。
写自定义类加载器:继承自ClassLoader抽象类,覆盖findClass方法(可以写自己的逻辑,最终调用defineClass得到字节码)。
代理
1. 要为系统中的各种借口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式将是一件非常麻烦的事情。
2. JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即为动态代理类。
3. JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
4. CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用
CGLIB库。
5. 代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
a. 在调用目标方法之前
b. 在调用目标方法之后
c. 在调用目标方法前后
d. 在处理目标方法异常的catch块中。
让jvm创建动态类及其实例对象,需要给它提供哪些信息
1. 生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知;
2. 产生的类字节码必须有一个关联的类加载器对象。
3. 生成的类中的方法的代码是怎样的,也得由我们提供。把我们的代码写在一个约定好了的接口对象的方法中,把对象传给它,它调用我的方法
动态代理对象在调用目标对象的方法时:
会将调用方法的Method对象传到内部的Handler对象,调用handler对象的invoke方法时该Method对象被传递到invoke方法上。实际调用过程是调用该
Method对象的invoke方法,该Method对象的invoke方法作用于目标对象上,并将返回值返回到该代理对象。