1. 程式人生 > >Java 基礎-反射與註解

Java 基礎-反射與註解

一、Class

1. Class 型別的獲取

  • Clazz.class;
  • clazz.getClass();
  • Class.forName(String className);

2. 根據 Class 型別建立類例項

Class clazzType = Clazz.class;

try{
    // Clazz 必需含有無參構造方法
    Clazz clazzBean = (Clazz)clazzType.newInstance();
}catch(Exception e){
    e.printStackTrace();
}

3. Class 載入

載入方式 實現 描述
靜態載入 new Clazz() 在編譯過程就載入
動態載入 (Class.forName(String className)).newInstance() 執行時才載入

二、反射

1. 反射的基本應用

class Clazz{
    public void print(String str){
        System.out.print("str");
    }
}
// 1. 獲取類資訊
Clazz clazz = new Clazz();
Class c = clazz.getClass();

try
{ // 2. 獲取類方法 Method m = c.getMethod("print", String.class); // 3. 實現方法的反射操作 m.invoke(clazz, "設定輸出內容"); }catch(Exception e){ e.printStackTrace(); }

2. 反射在泛型中的應用

反射操作位於編譯之後,即編譯後為泛型物件將失去泛型特徵

ArrayList<String> list = new ArrayList<String>();
Class c = list.getClass();

try
{ // 通過反射繞過編譯時對插入值型別的判斷 Method m = c.getMethod("add", Object.class); m.invoke(list, 1); }catch(Exception e){ e.printStackTrace(); }

三、註解

1. 概念理解

  • 成員型別必需是原始型別 及 String,Class, Annotation, Enumeration
  • 如果註解成員只有一個,則成員命名必需為 value(),在使用時可忽略成員名與賦值號(=)
  • 註解類可無成員物件,稱之為標識註解
// 元註解
@Target({ElementType.METHOD,ElementType.TYPE}) // 作用域
@Retention(RetentionPolicy.RUNTIME) // 宣告生命週期
@Inherited // 允許子類繼承,且僅繼承類註解
@Documented // 生成 javadoc 時包含註解資訊

// 使用@interface 定義註解
public @interface Description{

    // 無參無異常的成員宣告
    String sex();
    String author();

    // 成員的預設值宣告
    int age() default 18;
}
作用域 描述
@Target(ElementType.TYPE) 介面、類、列舉、註解
@Target(ElementType.FIELD) 欄位、列舉的常量
@Target(ElementType.METHOD) 方法
@Target(ElementType.PARAMETER) 方法引數
@Target(ElementType.CONSTRUCTOR) 建構函式
@Target(ElementType.LOCAL_VARIABLE) 區域性變數
@Target(ElementType.ANNOTATION_TYPE) 註解
@Target(ElementType.PACKAGE)
生命週期/註解分類 描述
@Retention(RetentionPolicy.SOURCE) 原始碼註解(僅原始碼中存在,編譯後不存在)
@Retention(RetentionPolicy.CLASS) 編譯時註解(原始碼與編譯後均存在)
@Retention(RetentionPolicy.RUNTIME) 執行時註解(執行時存在,影響邏輯處理)

2. 自定義

語法: @<註解名>(<成員名1>=<成員值>,<成員名2>=<成員值2>,…)

@Description(sex="I am boy", author="gzejia",age="25")
public class Clazz{

    @Description(sex="I am boy", author="gzejia",age="25")
    public String manSex(){
        return "boy";
    }
}

3. 註解解析

通過反射獲取類、函式或成員上的執行時註解資訊,從而實現動態控制程式執行的邏輯

try{
    // 1.使用類載入器載入類
    Class c = Class.forName("...Clazz");

    // 2.判斷是否存在註解資訊
    boolean isExist = c.isAnnotationPresent(Description.class);

    // 3.獲取類註解資訊
    if(isExist){
        Description d = (Description)c.getAnnotation(Description.class);
        System.out.println(d.sex());
    }

    // 4.獲取方法註解資訊
    Method[] ms = c.getMethods();
    for(Method m : ms){
        boolean isMExist = m.isAnnotationPresent(Description.class);

        if(isExist){
            Description d = (Description)m.getAnnotation(Description.class);
            System.out.println(d.author());
        }
    }

    // 獲取註解資訊方式二(以獲取方法註解資訊為例)
    for(Method m : ms){
        Annotation[] as = m.getAnnotations();

        for(Annotation a : as){
            if(a instanceof Description){
                Description d = (Description)a;
                System.out.println(String.valueOf(d.age()));
            }
        }
    }
}catch(Exception e){
    e.printStackTrace();
}