Java註解和反射

Hanyta發表於2024-05-01
  1. 元註解:負責註解其他的註解,Java定義了4個標準的meta-annotation型別
    @Target:用於描述註解的適用範圍
    @Retention:表示需要再什麼級別儲存該註解資訊,用於描述註解的生命週期(source<class<runtime)
    @Document:該註解江北包含在javadoc中
    @Inherited:說明子類可以繼承父類中的註解
  2. 自定義註解
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface MyAnnotation {
        //型別 引數名() 預設值
       String value() default "";
    }
    
  3. 動態語言:就是在執行程式碼時可以根據某些條件改變自身結構
    靜態語言:執行是結構不可變,如java,c++
    但java有一定的動態性,可以利用反射機制獲得類似動態語言的特性,使程式設計更加靈活
  4. 獲取Class物件的三種方式
    //一個Person類
    public class Person {
    private String name;
    private int age;
    
    public Person() {
    }
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
      }
    }
    //透過三種方式獲得Class物件
    import domain.Person;
    public class ReflectDemo {
        public static void main(String[] args) throws ClassNotFoundException {
            //1.Class.forName("全類名")
            Class cls0 = Class.forName("domain.Person");
            System.out.println(cls0);
    
            //2.類名.class
            Class cls1 = Person.class;
            System.out.println(cls1);
    
            //3.物件.getClass()
            Person p = new Person();
            Class cls2 = p.getClass();
            System.out.println(cls2);
        }
    }
    
  5. class,interface,[],enum,annotation,primitive type,void都有Class物件
  6. 類載入分為三個部分:載入,連線,初始化
    載入:將.class檔案的二進位制位元組流讀入記憶體,並在堆記憶體中為之建立Class物件,作為.class進入記憶體後的資料的訪問入口。
    為何取消方法區?
    方法區儲存類的後設資料資訊,我們不清楚一個程式到底有多少類需要被載入,且方法區位於JVM記憶體,我們不清楚需要給方法區分配多大記憶體,太小容易PermGen OOM,太大,在觸發Full GC時又極其影響效能,同時還存在一些記憶體洩露的問題
    連線:分為三個階段,驗證,準備,解析
    驗證:為了保證載入進來的位元組流符合JVM的規範,不會對JVM有安全性問題。
    準備:準備階段的主要任務是為類的類變數開闢空間並賦預設值。
    解析:該階段的主要職責為將Class在常量池中的符號引用轉變為直接引用,此處針對的是靜態方法及屬性和私有方法與屬性。
    初始化:該階段主要是為類的類變數初始化值的,在宣告類變數時,直接給變數賦值或者在靜態初始化塊為類變數賦值
  7. 反射的作用:動態建立物件,動態操作屬性,動態呼叫方法
  8. Class類的常用方法:
    getFields()—— 獲得類的public型別的屬性;getDeclaredFields()—— 獲得類的所有屬性;getField(String name)—— 獲得類的指定屬性;
    getMethods()—— 獲得類的public型別的方法;getMethod (String name,Class [] args)—— 獲得類的指定方法;
    getConstrutors()—— 獲得類的public型別的構造方法;getConstrutor(Class[] args)—— 獲得類的特定構造方法;
    newInstance()—— 透過類的無參構造方法建立物件;
    getName()—— 獲得類的完整名字;
    getPackage()—— 獲取此類所屬的包;
    getSuperclass()—— 獲得此類的父類對應的Class物件
    

相關文章