黑馬程序員_java基礎加強4

---------------------- android培訓java培訓、期待與您交流! ----------------------



8.JDK除了在java.lang下提供了3個基本的Annotation外,還在java.lang.annotation包下提供了4Meta Annotation(Annotation),這四個Annotation用於修飾其他Annotation定義。

 

@Retention  用於定義Annotation的生命週期,只有一個成員變量valuevalue取值只能是如下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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章