天天看點

java反射機制擷取父類屬性

首先檢視反射機制如何擷取類的方法的:

Class clazz = object.getClasss();
clazz.getDeclareFields();
Calzz.getFields();      

通過getClass()方法來擷取類的定義資訊,通過定義資訊再調用getFields()方法來擷取類的所有公共屬性,或者調用getDeclaredFields()方法來擷取類的所有屬性,包括公共,保護,私有,預設的方法,但是這裡有一點要注意的是這個方法隻能擷取目前類裡面顯示定義的屬性,不能擷取到父類或者父類的父類及更高層次的屬性的,

是以我們要想擷取類的所有屬性,還要擷取父類的屬性:

public static Field[] getAllFields(Object object){
  Class clazz = object.getClass();
  List<Field> fieldList = new ArrayList<>();
  while (clazz != null){
    fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
    clazz = clazz.getSuperclass();
  }
  Field[] fields = new Field[fieldList.size()];
  fieldList.toArray(fields);
  return fields;
}
      

這個方法通過while循環及getSuperClass()方法擷取目前類的父類再進行getDeclaredFields()即可,注意這個方法傳回的是一個Field數組,然後如果我們想要把這些屬性拼接到一起,當然是使用連結清單更友善一些,利用Arrays.asList()方法将數組轉化為連結清單,注意:這個方法傳回的是一個List<>也就是抽象清單,是以要将其再用ArrayList初始化一次得到的清單才可變,否則得到的是一個不可變的清單.然後我們再利用清單的toArray()方法将清單轉為數組,注意:這裡又有一個坑,這個方法提供了兩種實作:

Object[] toArray();
<T> T[] toArray(T[] a);      

第一種無參,但注意,傳回值類型為Object數組類型,直接這麼寫肯定會報錯,但是如果強制轉換為需要的類型,則在運作時會抛這樣一個異常:

java反射機制擷取父類屬性
  • ​ 程式會告訴你無法這麼轉換,是以這裡要注意

    第二種的參數就填你要轉換的數組就可以,但是他要求數組的長度是等于連結清單的長度的,否則會編譯不通過,是以得到連結清單之後在初始化數組即可

  • 然後這裡在測試時導師提到了一個點就是循環依賴的問題,擔心while會跳不出來,但是這裡其實跟屬性的具體類型是無關的,是以不會出現這個問題,但是就順便了解了下循環依賴的相關概念,比如我定義兩個類:
class ClassA {
    int a;
    ClassB ab;
    public ClassA(){
        ab = new ClassB();
    }
}
class ClassB extends ClassA {
    int b;
    ClassA ba;

    public ClassB() {
        this.ba = new ClassA();
}      

乍一眼看上去有很大問題嘛,怎麼A是B的父類,A裡面還有一個屬性是B類的,其實這個問題跟繼承關系也不大,隻不過繼承關系會讓人印象更深刻,因為這段代碼編譯是可以通過的,那麼我們來執行個體化一個B類看看會發生什麼:

異常資訊