今天在面試的時候遇到一個非常nice的面試官,當時問到了如何通過反射來獲取私有屬性,
雖然本人之前也有做過,不過今天面試官一問頓時一臉懵逼,於是打算寫這篇博客記錄下來。先來看下我們的javaBean
public class Test {
private String name;
private int age;
private Test(int age){
this.age = age;
}
private void speak(String name){
System.out.println("我的名字是:"+name);
}
public Test(String name) {
this.name = name;
}
}
首先,我們要了解三個反射包中的類:
Constructor:代表類的單個構造方法,通過Constructor我們可執行一個類的某個構造方法(有參或者無參)來創建對象時。
Method:代表類中的單個方法,可以用於執行類的某個普通方法,有參或無參,並可以接收返回值。
Field:代表類中的單個屬性,用於set或get屬性
AccessibleObject:以上三個類的父類,提供了構造方法,普通方法,和屬性的訪問控制的能力。
使用Class類中的方法可以獲得該類中的所有Constructor對象,Method對象,和Field對象。
但是任然無法訪問私有化的構造方法,普通方法,和私有屬性,此時我們可以使用他們繼承父類(AccessibleObject)中的
setAccessible()方法,來設置或取消訪問檢查,以達到訪問私有對象的目的。
Step1:獲取私有屬性
public static void main(String[] args) throws NoSuchFieldException {
// TODO Auto-generated method stub
/*
* 使用反射來創建構造方法私有化的對象
* */
//1:獲取類的無參構造方法
Test test = new Test("張三");
Method[] methods = Test.class.getMethods();
Field[] fields = Test.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
try {
System.out.println(fields[i].get(test));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(fields[i].getName());
}
} 然后,我們再來看一下輸出的:
張三
name
0
age
Step2:獲取私有方法
Method[] methods2 = Test.class.getDeclaredMethods();
for (int i = 0; i < methods2.length; i++) {
methods2[i].setAccessible(true);
System.out.println(methods2[i].getName());
} 然后,我們再來看一下輸出的:
speak
Step3:調用私有方法
Test test = new Test("張三");
Method[] methods = Test.class.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
methods[i].setAccessible(true);
try {
methods[i].invoke(test,"成功調用");
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(methods[i].getName());
}
這樣,我們就獲得了私有屬性的值啦~~當然,凡事有利就有弊,然后我們再來說一下java反射的優缺點;
優點:
1:能夠運行時動態獲取類的實例,大大提高了系統的靈活性和擴展性;
2:與java動態編譯相結合,可以實現無比強大的功能。
缺點:
1:使用反射的性能較低;
2:使用反射來說相對不安全;
3:破壞了類的封裝性,可以通過反射來獲取這個類的屬性,和私有方法。
