java反射機制獲取對象中父類屬性對象


今天有朋友問,繼承會繼承父類的私有屬性和私有方法嗎。回答當然是可以的,只是不能直接訪問(例如對於父類的私有屬性,可以借助從父類中繼承的get方法來獲得該值)。

當時也想到可以通過反射的方式來獲取父類中私有屬性的值。一開始使用getDeclaredFileds(),但發現只能獲取子類的相關的屬性對象,后面結合getSuperclass()方法先獲取父類的字節碼對象進而獲取了子類中的所有屬性對象。具體代碼如下:

通過 getDeclaredFileds()方法獲取屬性對象

父類:

public class Person {
    public String name;
    private int age;
}

子類:

public class Student extends Person {
    public String className;
    private String gender;
}

測試:

public class Demo {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Student student = new Student();

        // 通過子類的字節碼對象獲取獲取所有屬性
        Class<Student> studentClass = Student.class;
        Field[] declaredFields = studentClass.getDeclaredFields();

        for (Field declaredField : declaredFields) {  // 打印所有的屬性字段
            System.out.println(declaredField);
        }
    }
}

運行結果:

public java.lang.String Demo.Student.className
private java.lang.String Demo.Student.gender

可以看到通過getDeclaredFileds()方法可以獲取當前類私有屬性對象和公有屬性對象,當不能獲取父類相關的屬性對象。

結合getSuperclass()方法獲取父類的屬性對象

由於反射機制只能獲取當前類的屬性對象,為了獲取其父類的屬性對象就需要先通過getSuperclass獲取該當前類的父類字節碼對象,因為類存在對繼承這里使用了while(clazz != null)遍歷了所有的父類字節碼對象。具體代碼如下:

public class Demo {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Student student = new Student();

        Class clazz = Student.class;
        List fieldsList = new ArrayList<Field[]>();  // 保存屬性對象數組到列表
        while (clazz != null) {  // 遍歷所有父類字節碼對象
            Field[] declaredFields = clazz.getDeclaredFields();  // 獲取字節碼對象的屬性對象數組
            fieldsList.add(declaredFields);

            clazz = clazz.getSuperclass();  // 獲得父類的字節碼對象
        }

        for (Object fields:fieldsList) {  // 打印當前類以及其父類的多有屬性對象
            Field[] f = (Field[]) fields;
            for (Field field : f) {
                System.out.println(field);
            }
        }
    }
}

結果:

public java.lang.String Demo.Student.className
private java.lang.String Demo.Student.gender
public java.lang.String Demo.Person.name
private int Demo.Person.age

上述代碼還可以進行改進,可以將Filed[]數組轉換為List<>然后再將其拼接至ArrayList上,這樣后面遍歷Filed對象也不用嵌套循環了。

public class Demo {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Student student = new Student();

        Class clazz = Student.class;
        List fieldsList = new ArrayList<Field>();
        while (clazz != null) {  // 遍歷所有父類字節碼對象
            Field[] declaredFields = clazz.getDeclaredFields();
            fieldsList.addAll(Arrays.asList(declaredFields));  //將`Filed[]`數組轉換為`List<>`然后再將其拼接至`ArrayList`上

            clazz = clazz.getSuperclass();  // 獲得父類的字節碼對象
        }

        for (Object field : fieldsList) {  // 打印當前類以及其父類的多有屬性對象
            System.out.println(field);
        }
    }
}

參考

Java反射機制獲取父類屬性: https://www.jianshu.com/p/6fe3e0e185ac


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM