註解、反射
Annotation(註解)
(1)作用:可以被其他程式(比如:編譯器)讀取
(2)格式:“@註釋名”。在程式碼中存在的,還可新增一些引數值
如:@SuppressWarnings(value=”unchecked”) -- 壓制警告
(3)可以附加在package(包),class(類),method(方法),field等上面。可以通過反射機制實現對這些元資料的訪問
內建註釋---(常見)
(1)@Override(方法重寫)
(2)@SuppressWarnings(壓制警告)
(3)Deprecated(過時)
元註釋
(1)元註釋作用:負責註解其他註解
@Target
@Retention:表示註釋在什麼地方還有效,用於描述註解的生命週期(有三個值:SOURCE<CLASS<RUNTIME)
@Document:說明該註解將包含在javadoc中
@Inherited:說明子類可以繼承父類中的註解
範例:(註解)
package collection;
import java.lang.annotation.*;
// 測試元註解
public class Demo11 {
自定義註解
(1)使用@Interface自定義註解,自動繼承java.lang.annotation.Annotation介面
格式:@interface 註解名{定義內容}
(2)返回值型別就是引數的型別(返回值只能是基本資料,Class,String,enum)
(3)註解引數:引數型別 引數名();
(4)如果註解只有一個引數,建議引數名使用value,呼叫註解時,可不用寫引數名,直接寫引數
範例:(自定義註解)
package text;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Text3 {
// 註解可以顯示賦值,如果沒有預設值,必須給註解賦值
反射
(1)只要元素型別與維度一樣,就是同一個Class
範例:
package collection;
import java.lang.annotation.ElementType;
public class Deom13 {
public static void main(String[] args) {
Class c1 = Object.class; //類
Class c2 = Comparable.class; //介面
Class c3 = String[].class; //一維陣列
Class c4 = int[][].class; //二維陣列
Class c5 = Override.class; //註解
Class c6 = ElementType.class; //列舉
Class c7 = Integer.class; //基本資料型別
Class c8 = void.class; //void
Class c9 = Class.class; //Class
}
}
類載入與ClassLoader
(1)載入——連結——初始化
注:通過反射獲取執行時類的完整結構
Field、Method、Constructor、Superclass、Interface、Annotation
注:不能直接操作私有屬性或方法,操作私有屬性或方法時,需要關閉程式的安全檢測屬性或方法setAccessible(true)
setAccessible
(1)Method和Filed、Constructor物件都有setAccessible()方法
(2)setAccessible作用是啟動和禁用安全檢查的開頭
(3)引數值為true,表示原本無法訪問的私有成員也可以訪問
範例:
package collection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Demo14 {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("collection.Son");
Object obj=c1.newInstance();
Field name = c1.getDeclaredField("name");
// 不能直接操作私有屬性,需要關閉程式的安全檢測,屬性或方法setAccessible(true)
name.setAccessible(true);
name.set(obj,"小藍");
System.out.println(name.get(obj));
}
}
class Son{
private String name;
private int age;
public Son() { }
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
獲取泛型資訊
(1)ParameterizedType:表示一種引數化型別
(2)GenericArrayType:表示一種元素型別是引數型別或型別變數的陣列型別
(3)TypeVariable:是各種型別變數的公共父介面
(4)WildcardType:代表一種萬用字元型別表示式
getGenericExceptionTypes(); // 獲得泛型異常資訊 getGenericParameterTypes(); // 獲得泛型引數資訊 getGenericReturnType(); // 獲得泛型返回值資訊
範例:
package collection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class Demo15 {
public void test01(Map<String,Integer> map, List<String> list){
System.out.println("test01");
}
public Map<String,Integer> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = Demo15.class.getDeclaredMethod("test01", Map.class, List.class);
Type[] getGenericParameterTypes =method.getGenericParameterTypes();
// 獲得泛型引數資訊
for (Type getGenericParameterType : getGenericParameterTypes) {
System.out.println("## "+getGenericParameterType);
// 獲得泛型引數資訊
if (getGenericParameterType instanceof ParameterizedType){
// 判斷泛型引數是否是引數化型別
Type[] actualTypeArguments = ((ParameterizedType) getGenericParameterType).getActualTypeArguments(); // 取得真實引數型別
// 強轉為引數化型別
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
System.out.println("=====================");
method=Demo15.class.getMethod("test02");
Type genericReturnType = method.getGenericReturnType();
// 取得返回值引數型別
if (genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
獲取註解資訊
(1)獲得註解:Class類物件.getAnnotations()
(2)獲得指定的註解:Class類物件.getAnnotation(註解名.class)
範例:(通過反射獲得註解)
package collection;
import java.lang.annotation.*;
public class Demo16 {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("collection.Student");
// 通過反射獲得註解
Annotation[] annotations=c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation); //@collection.Table(value=db_student)
}
// 獲得註解的value的值
Table table = (Table) c1.getAnnotation(Table.class);// 獲得類指定的註解
String value = table.value();
System.out.println(value); // db_student
// 獲得類指定的註解
java.lang.reflect.Field name = c1.getDeclaredField("name");
Field annotation = name.getAnnotation(Field.class); // 獲得指定的註解
System.out.println(annotation.columnName()); //db_name
System.out.println(annotation.type()); //varchar
System.out.println(annotation.length()); //3
}
}