1. 程式人生 > >day26基礎加強(泛型、萬用字元、註解、反射 註解使用)

day26基礎加強(泛型、萬用字元、註解、反射 註解使用)

泛型
1、具有一個或多個泛型變數的型別被稱之為泛型類
    class A<T>{}

2、在建立泛型類例項時,需要為其型別變數賦值
A<String> a = new A<String>();
    如果建立例項時,不給型別變數賦值,那麼會有一個警告。

3、泛型方法:具有一個或多個型別變數的方法,稱之為泛型方法
class A<T>{
    public T fun(T t1){

    }
}
fun()方法不是泛型方法,是泛型類中的一個方法
public <T>T fun (T t1){} -->是泛型方法
泛型方法和泛型類沒什麼關係,泛型方法不一定非要在泛型類中。

4、泛型在類中或方法中的使用
    泛型類中使用泛型
        成員型別
        返回值和引數型別
        區域性變數的引用上

class A<T>{
    private T bean;//泛型可在成員變數上使用
    public T fun(T t){}//泛型可以在類中的方法上(返回值和引數型別)使用

    public void fun2(){//泛型還可以在區域性變數的引用型別上使用
        T b=...
        new T();//不行
    }
}

5、泛型的繼承和實現
class A<T>{}
class AA extends A<String>{}//不是泛型類,只是他爸爸是泛型類

5.1、繼承泛型類
    子類不是泛型類:需要給父類傳遞型別常量
        當給父類傳遞的型別常量為String時,那麼在父類中所有T都會被String替換
    子類是泛型類,可以給父類傳遞型別常量,也可以傳遞型別變數

class AA1 extends A<Integer>{}
class AA3<E> extends A<E>{}

泛型的萬用字元
1、萬用字元使用的場景
    方法的形參

2、萬用字元的優點
    使方法更加通用

3、萬用字元分類
    無界通配:?
    子類限定:? extend Object
    父類限定: ? super Integer

4、萬用字元缺點
    使變數使用上不再方便
    無界:引數和返回值為泛型的方法,不能使用
    子類:引數為泛型的方法不能使用
    父類:返回值為泛型的方法不能使用

5、比較萬用字元
boolean addAll(Collection<E> c)

List<Number> numList = new ArrayList<Number>();
List<Integer> intList = new ArrayList<Integer>();
numList.addAll(intList);//addAll(Collection<Number> c),傳遞的是List<Integer>

boolean addAll(Collection<? extends E> c)

List<Number> numList = new ArrayList<Number>();
List<Integer> intList = new ArrayList<Integer>();
numList.addAll(intList);//addAll(Collection<? extends Number> c),傳遞的是List<Integer>

註解【配置檔案 需要有人讀 否則無意義,往往是框架讀比如tomcat】
1、什麼是註解
    語法:@註釋名稱
    註解的作用:替代xml配置檔案
        servlet3.0中,就可以不再使用web.xml,而是所有配置都使用註解
    註解是由框架來讀取使用 

2、註解
    定義註解類:框架的工作
    使用註釋:我們的工作
    讀取註釋(反射):框架的工作

3、定義註解類
    class A{}
    interface A{}
    enum A{}
    @interface A{} 所有的註解都是Annotation的子類

 4、使用註解
    可以把註解作用在:類、方法、屬性、構造器、方法引數、區域性變數也可以把註解作用在包上[沒啥用]

 @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnn{}
 下面的程式碼會出錯
    @MyAnn
    package xx;
    public class A{}
    因為java不讓這麼註解包,如果想給包添加註解必須再建立一個檔案:package-info.java檔案,然後在這個方法中給出對包的註解

    package-info.java
    @MyAnn package xx

    反射包上的註解
    Package p = Package.getPackage("my.xx");
    MyAnn myAnn = p.getAnnocation(MyAnn.class);

    註解的作用目標
        類
        方法
        構造器
        引數
        區域性變數
        包

5、註解的屬性
    定義屬性
        格式:型別 屬性名();
        @interface MyAnno1{
            int age();
            String name();
        }
    使用註解時給屬性賦值
        @MyAnno1(age=10,name="zhangSan")
    註解屬性的預設值:在定義註解時,可以給註解定義預設值
        int age() default 100;
        在使用註解時,可以不給帶有預設值的屬性賦值
    名為value的屬性的特權
        當使用註解時,如果只(僅一個的時候)給名為value的屬性賦值時,可以省略"value=",
    例如@MyAnno1(value="hello")可以書寫成@MyAnno1("hello")
    註解屬性的型別
        8中基本型別
        String
        Enum
        Class
        註解型別
        以上型別的一維陣列型別 包裝類不行比如Integer

        當給陣列型別的屬性賦值時,若陣列元素的個數為1時,可以省略大括號
@MyAnno1(
    a=100,
    b="hello",
    c=MyEnum1.A,
    d=String.class,
    
[email protected]
(aa=1,bb="2"), f={"a","b"}, h=100 ) public class Demo3 { } @interface MyAnno1{ int a(); String b(); MyEnum1 c(); Class d(); MyAnno2 e(); String[] f(); int[] h(); } @interface MyAnno2{ int aa(); String bb(); } //列舉要求是其中的一個 enum MyEnum1{ A,B,C } 6、註解的作用目標限定以及保定策略限定 6.1讓一個註解,它的作用目標只能在類上,不能在方法上,這就叫作用目標的限定 在呼叫註解時,給註解添加註解,這個註解是@Target 列舉就幾個選項 @Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD}) @interface MyAnno1{ } 6.2保留策略 原始碼檔案(source):註解只在原始碼中存在,當編譯時就被忽略了 位元組碼檔案(class):註解在原始碼中存在,然後編譯時會把註解資訊放到了class檔案,但JVM在載入類時,會忽略註解 JVM中(runtime):註解在原始碼、位元組碼檔案中存在,並且在JVM載入類時,會把註解載入到JVM內中(唯一可反射的註解) 6.3、限定註解的保留策略 使用 @Retention(RetentionPolicy.RUNTIME) @interface MyAnno1{ } 7、讀取註解(反射) 反射泛型資訊 Class-->Type getGenericSupperclss() Type-->ParameterizedType:把Type強轉成ParameterizedType型別 ParameterizedType-->引數化型別=A<String> ParameterizedType:Type[] getActuallTypeArguments(),A<String>中的String Type[]就是Class[],就得到了型別引數 abstract class A<T>{ public A(){ /* * 獲取子類傳遞的泛型資訊,得到一個class */ // Class clazz = this.getClass();//得到子類的型別 // Type type = clazz.getGenericSuperclass();//獲取傳遞給父類的引數化型別 // ParameterizedType pType = (ParameterizedType) type;//就是A<String> // Type[] types = pType.getActualTypeArguments();//就是一個Class陣列 // Class c = (Class) types[0];//就是String // Class c = null; // System.out.println(c.getName());//String或Integer Class c= (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; System.out.println(c.getName()); } } 反射註解 1、要求 註解的保留策略必須是RUNTIME 2、反射註解需要從作用目標上返回 類上的註解,需要使用Class獲取 方法上的註解,需要Method來獲取 構造器的註解,需要Constructor來獲取 成員上的,需要Field來獲取 Class: Method、Constructor、Field:AccessibleObject 都有一個方法: Annotation getAnnotation(Class):返回目標上指定型別的註解 Annotation[] getAnnotations:返回目標上所有註解