1.反射是什么
反射就是java的一種機制,在程序運行的時候,可以動態的獲取類中的方法和類中的屬性,在此我們對其進行動態的修改添加或者刪除功能,而不影響其他功能。
2.通過反射獲取類中私有方法和屬性
1.先創建一個對象
public class Demo {
private String name;
public void getPublicMethod(String name){
System.out.println(this.name +"調用共用方法" + name);
}
private void getPrivateMethod(String name){
System.out.println(this.name +"調用私有方法" + name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.編寫一個簡單java運行類
public class TestMain {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
// 1.獲取demo的類
Class cl = Class.forName("com.zhaott.classloader.Demo");
// 2.創建demo的對象
Demo demo = (Demo)cl.newInstance();
// 3. 獲取demo類中的getPrivateMethod方法
Method method = cl.getDeclaredMethod("getPrivateMethod",String.class);
// 4. 設置getPrivateMethod方法能夠訪問
method.setAccessible(true);
// 5. 執行剛剛獲取getPrivateMethod的方法
method.invoke(demo,"小明");
// 6.獲取demo類中的"name"屬性
Field field = cl.getDeclaredField("name");
// 7.設置name屬性可用
field.setAccessible(true);
// 8.為demo對象中的name屬性賦值
field.set(demo,"小紅");
// 9.再次執行獲取的getPrivateMethod的方法
method.invoke(demo,"小明");
}
}
3.查看執行結果
圖1.png
3.通過反射獲取類中公有方法和屬性
1.先創建一個對象
public class Demo {
public String name;
public void getPublicMethod(String name){
System.out.println(this.name +"調用共用方法" + name);
}
private void getPrivateMethod(String name){
System.out.println(this.name +"調用私有方法" + name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.編寫一個簡單java運行類
public class TestMain {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
// 1.獲取demo的類
Class cl = Class.forName("com.zhaott.classloader.Demo");
// 2.創建demo的對象
Demo demo = (Demo)cl.newInstance();
// 3. 獲取demo類中的getPublicMethod方法
Method method = cl.getMethod("getPublicMethod",String.class);
// 4. 執行剛剛獲取getPublicMethod的方法
method.invoke(demo,"小明");
// 6.獲取demo類中的"name"屬性
Field field = cl.getField("name");
// 7.為demo對象中的name屬性賦值
field.set(demo,"小紅");
// 8.再次執行獲取的getPublicMethod的方法
method.invoke(demo,"小明");
}
}
3.查看執行結果
圖2.png
4.分析兩次執行的結果
相信到了這里大家也已經把案例敲出來了,但是仔細的同學就會發現兩次執行的結果不同,同時代碼也有所不同了,而且相信還有一部分人把代碼進行修改,出現了各種各樣的錯誤,這里我就一一給大家解惑。
- 通過Class cl = Class.forName("com.zhaott.classloader.Demo");獲取了cl的類,(這里方法不止一種,此處就先使用該種方法)
- 第一次使用的cl.getDeclaredMethod("getPrivateMethod",String.class);
第二次使用的是cl.getMethod("getPublicMethod",String.class)
在這里對getDeclaredMethod(String str,Object...)和getMethod(String str,Object...)做一下區分
getDeclaredMethod是可用獲取當前類中的所有方法,其中不包括繼承的方法和實現的方法,也就是說不包含父類中的方法和父接口中的方法,包括包含public、protected和private方法
getMethod是可用獲取當前類中的公共方法,包括繼承的方法和實現的方法,
也就是包含父類中的方法和父接口中的方法,但是只能包含public修飾的公共方法
getDeclaredMethod(String str,Object...)參數值,第一個參數值是要初始化的參數名,第二個參數是要初始化方法的參數類型例如:cl.getDeclaredMethod("getPrivateMethod",String.class)
getMethod(String str,Object...)使用方法和getDeclaredMethod一樣
- method.invoke(對象,"方法的參數值")
- cl.getDeclaredField("name")和cl.getField("name")的區別和上面介紹的獲取方法的用法一樣
- field.set(對象,"屬性值");
此處還會有一個錯誤,如果在對象中該屬性為私有屬性,但是沒有get/set方法,就會拋出異常,異常如下:圖3.png
- 介紹一下method.setAccessible(true)的使用
當我們獲取的方法為私有方法,我們獲取的屬性為私有屬性的時候,需要在獲取到后調用method.setAccessible(true)/field.setAccessible(true)設置方法/屬性可用性,如果不設置可用性此時會拋出異常,異常如下:圖4.png
相信經過兩個簡單案例可以讓大家對反射有一定了解,還有反射使用的一些注意事項,反射在我們開發中隨處可見,也許我們沒用到,但是我們使用的框架中取經常使用,還有動態代理中就可以使用反射機制,寫有不對之處,希望大家隨時給出自己的意見。