您的位置:首页 > 职场人生

黑马程序员_java基础加强4

2012-03-20 18:16 393 查看
---------------------- 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: