---------------------- android培训、java培训、期待与您交流! ----------------------
8.JDK除了在java.lang下提供了3个基本的Annotation外,还在java.lang.annotation包下提供了4个Meta Annotation(元Annotation),这四个Annotation用于修饰其他Annotation定义。
@Retention 用于定义Annotation的生命周期,只有一个成员变量value,value取值只能是如下3个:
RetentionPolicy.CLASS:编译器将把注释记录在class文件中,当运行java程序时,jvm不在保留注释,这是默认值。
RetentionPolicy.RUNTIME:编译器将把注释记录在class文件中,当运行java程序时,jvm也会保留注释,程序可以通过反射获取该注释。
RetentionPolicy.SOURCE:编译器直接丢弃这种策略的注释。
应用如11注释的定义。
@Target 指定被修饰的注释能用于修饰哪些程序元素。成员value有如下值:
ElementType.ANNOTATION_TYPE:只能修饰注释
ElementType.CONSTRUCTOR:只能修饰构造器
ElementType.FIELD:只能修饰成员变量(包括枚举常量)
ElementType.LOCAL_VARIABLE:只能修饰局部变量
ElementType.METHOD:只能修饰方法
ElementType.PACKAGE:只能修饰包定义
ElementType.PARAMETER:只能修饰参数
ElementType.TYPE:只能修饰类、接口(包括注释类型)或枚举
应用如11注释的定义。
@Documented 当修饰某个注释后,再用这个注释去修饰一个程序元素,当提取被修饰程序元素所在类时,程序元素的注释(生命周期为RetentionPolicy.RUNTIME)也会被提取。
@Inherited 被此元注释修饰的注释具有继承性。即:某个类使用了A注释(定义该注释时被@Inherited修饰),则该类的子类自动具有A注释。
9.泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。例:
Set<String> set=new HashSet<String>();
set.add("di yi ge");
set.add("hahaha");
System.out.println(set.size());//2
Method cla=set.getClass().getMethod("add", Object.class);
cla.invoke(set, 2);
System.out.println(set.size());//3
10.泛型基础:
ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:
整个称为ArrayList<E>泛型类型
ArrayList<E>中的E称为类型变量或类型参数
整个ArrayList<Integer>称为参数化的类型
ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
ArrayList<Integer>中的<>念着typeof
ArrayList称为原始类型
参数化类型与原始类型的兼容性:
参数化类型可以引用一个原始类型的对象,编译报告警告,例如,
Collection<String> c = new Vector();//可以
原始类型可以引用一个参数化类型的对象,编译报告警告,例如,
Collection c = new Vector<String>();//原来的方法接受一个集合参数,新的类型也要能传进去
参数化类型不考虑类型参数的继承关系:
Vector<String> v = new Vector<Object>(); //错误!
Vector<Object> v = new Vector<String>(); //也错误!
编译器不允许创建泛型变量的数组。即在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:
Vector<Integer> vectorList[] = new Vector<Integer>[10];
思考题:下面的代码会报错误吗?
Vector v1 = new Vector<String>();
Vector<Object> v = v1;//不会
11.泛型通配符:
限定通配符的上边界:
正确:Vector<? extends Number> x = new Vector<Integer>();
错误:Vector<? extends Number> x = new Vector<String>();
限定通配符的下边界:
正确:Vector<? super Integer> x = new Vector<Number>();
错误:Vector<? super Integer> x = new Vector<Byte>();
提示:限定通配符总是包括自己。
?只能用作引用,不能用它去给其他变量赋值
Vector<? extends Number> y = new Vector<Integer>();
Vector<Number> x = y;
上面的代码错误,原理与Vector<Object > x11 = new Vector<String>();相似,只能通过强制类型转换方式来赋值。
12.类泛型定义时机:如果类的实例对象中的多处都要用到同一个泛型参数。
定义格式:
class GenericDAO<T> {
public void save(T t) {}
public void delete(int id) {}
public T findById(int id){
return null;}
public Set<T> findByConditions(String conditions) {
return null;}
public static <E> E add(E x,E y){//在类泛型中定义方法特有泛型
return null;
}
}
注意:在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。
当一个变量被声明为泛型时,则这个变量只能被实例变量、方法和内部类调用,而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。
13.可以通过反射得到泛型类的实际类型参数(了解),代码示例如下:
public class CenericReflect {
public static void main(String[] args) throws Exception {
//Vector<Date>和Vector<String>用的同一份字节码Vector.class
Method applyMethod = CenericReflect.class.
getMethod("applyVector", Vector.class);
Type[] types = applyMethod.getGenericParameterTypes();
ParameterizedType pType = (ParameterizedType)types[0];
System.out.println(pType.getRawType());
System.out.println(pType.getActualTypeArguments()[0]);
}
public static void applyVector(Vector<Date> v1){
}
}
---------------------- android培训、java培训、期待与您交流! ----------------------
详细请查看: http://edu.csdn.net/heima