Javaweb學習筆記——(二十七)——————泛型、泛型的萬用字元、反射泛型資訊、反射註解、註解
泛型 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> extend A<E> {}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
泛型的萬用字元 1.萬用字元使用的場景 方法的形參
2.萬用字元的優點 使方法更加通用
3.萬用字元分類 無界通配
4.萬用字元缺點 使變數使用上不再方便 無界:引數和返回值為泛型的方法,不能使用 子類:引數為泛型的方法不能使用 父類:返回值為泛型的方法不能使用
5.比較萬用字元 boolean addAll(Collection<E> c)
List<Number> numList = new ArrayList<Number>(); List<Integer> intList = new ArrayList<Integer>(); numList.addList(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>
反射泛型資訊 Class --> Type getGenericSupperclass() Type --> ParameterizedType, 把Type強轉為PrarameterizedType型別 ParamerterizedType:Type[] getActualTypeArguments(), A<String>中的String Type[]就是Class[],我們就可以得到型別引數了
class< A<T>{ public A(){ /* 在這裡獲取子類傳遞的泛型資訊,要得到一個Class */ // Calss clazz = this.getClass();//得到子類的型別 // Type type = clazz.getGenericSuperclass();//獲取傳遞給服父類引數化型別 // ParameterizedType pType = (ParameterizedType)type;//它就是A<String> // Type[] types = pType.getActualTypeArguments();//它就是一個Class陣列
Class c = (Class)(ParameterizedType)this.getClass() .getGenericSuperclass()).getActualTypeArguments()[0];
System.out.println(c.getName()); } }
class B extends A<String> {
}
class C extends A<Integer> {
}
反射註解: 1.要求: *註解的保留策略庫必須是RUNTIME 2.反射註解需要從作用目標上返回 *類上的註解,需要使用Class來獲取 *方法上的註解,需要Mehtod來獲取 *構造器上的註解,需要Construcator來獲取 *成員上的,需要使用Field來獲取
Class Method、Comstructor、Field:AccessibleObject 他們都有一個方法: *Annotation getAnnotation(Class),返回目標上指定型別的註解 *Annotation[] getAnnotations(),返回目標上所有註解
註解 1.什麼是註解 語法:@註解名稱 註解的作用:替代xml配置檔案 servlet3.0中,就可以不再使用web.xml檔案,而是所有配置都使用註解 註解是由框架來讀取使用的
2.註解的使用 *定義註解類:框架的工作 *使用註解:我們的工作 *讀取註解(反射):框架的工作
3.定義註解類 Class A {} interface A{} enum A{} @interface A{}//所有的註解都是Annotation的子類
4.使用註解 註解的作用目標: *類 *方法 *構造器 *引數 *區域性變數 *包
5.註解的屬性 *定義屬性: >格式: @interface MyAnno1{ int age(); String name();
}
*使用註解時給屬性賦值 >@MyAnno1(age=100, name="zhangSan") *註解屬性的預設值:在定義註解時,可以給註解指定預設值 >int age() default 100; >在使用註解時,可以不給帶有預設值的屬性賦值 *名為value的屬性的特權 >當使用註解時,如果只給名為value的屬性賦值時,可以省略“value=”,例如:@MyAnno1(value="hello"),可以書寫成@MyAnno1("hello") *註解屬性的型別 >8中基本型別 >String >Enum >Class >註解型別 >以上型別的以為陣列型別
當給陣列型別的屬性賦值時,若陣列元素的個數為1時,可以省略大括號 @MyAnno1( a=100, b="hello", c=MyEnum1.A, d=String.class, [email protected](aa=200, bb="world"), f=100 ) public class Demo3 {
}
@interface MyAnno1 { int a(); String b(); MyEnum1 c(); Class d(); MyAnno2 e(); int[] f(); }
6.註解的作用目標限定已以及儲存策略限定 6.1讓一個註解,它的作用目標只能在類上,不能在方法上,這就叫做目標的限定 *在定義註解時,給註解添加註解,這個註解是@Target
@Target(value={ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @interface MyAnno1 {
}
6.2保留策略 *原始碼檔案(SOURCE):註解只在原始碼中存在,當編譯時就被忽略了 *位元組碼檔案(CLASS):註解在原始碼中存在,然後編譯時會把註解資訊放到class檔案,但是JVM在載入類時,會忽略註解 *JVM中(RUNTIME):註解在原始碼、位元組碼檔案中存在,並且在JVM載入類時,會把註解載入到JVM記憶體中(它是唯一可以反射註解)
限定註解的保留策略
@Retention(RetentionPolicy.RUNTIME) @interface MyAnno1 {
}
7.讀取註解(反射)
================================================
模擬註解的使用場景