java語(yǔ)言中,在一個(gè)類中,,為了不讓外界訪問到有的屬性和方法,,通常將其設(shè)置為private,用正常的方式(對(duì)象名.屬性名,,對(duì)象名.方法名)將無(wú)法訪問此屬性與方法,,但有沒有其他方法可以訪問呢?答案是有的,,這就是java反射帶來(lái)的便利,。利用反射訪問類的私有屬性及方法如下:
1.準(zhǔn)備一個(gè)java類,包含私有屬性及方法:
- //Exam.java
- public class Exam{
- private String field1="私有屬性";
- public String field2="公有屬性";
- public void fun1(){
- System.out.println("fun1:這是一個(gè)public訪問權(quán)限方法");
- }
-
- private void fun2(){
- System.out.println("fun2:這是一個(gè)private訪問權(quán)限方法");
- }
-
- private void fun3(String arg){
- System.out.println("fun3:這是一個(gè)private訪問權(quán)限且?guī)?shù)的方法,參數(shù)為:"+arg);
- }
-
- }
將其編譯成class,,然后刪除java源文件,。注意:刪除java源文件并非必須,但是在實(shí)際情況中,,我會(huì)使用的往往不是java源文件,,而是jar包,而jar包中的文件都是class,,所以為了貼近實(shí)際的情況,,將Exam.java編譯成Exam.class文件后,刪除Exam.java文件,,只保留Exam.class文件,。
2.獲取類中屬性及方法的信息
第一步做好后,接下來(lái)進(jìn)行第二步:獲取類中屬性及方法的信息,。對(duì)于一個(gè)class文件,無(wú)法查看源碼,,如何獲取類中屬性及方法的信息呢?很自然地,,我們會(huì)想到利用java反射功能,得到類的屬性,、方法:
- //Test01.java
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
-
- public class Test01 {
- public static void main(String args[]){
- Exam e=new Exam(); //初始化Exam實(shí)例
- System.out.println("獲取類中所有的屬性:");
- Field field[] = e.getClass().getFields();
- for(Field f : field){
- System.out.println(f);
- }
- System.out.println("獲取類中所有的方法:");
- Method[] method = e.getClass().getMethods();
- for(Method m : method){
- System.out.println(m);
- }
-
- }
- }
運(yùn)行結(jié)果如下:
從運(yùn)行結(jié)果可以看到,,獲取的屬性中只有field2,而獲取的方法中似乎多了好多類中沒有的,但最主要的是,,無(wú)論是屬性還是方法,,都是public聲明的,沒有得到private聲明的屬性或方法,。由此可以推斷:
1.聲明為private的屬性或方法無(wú)法通過(guò)這種途徑來(lái)獲取,。
2.結(jié)果中多出來(lái)的方法為從Object類中繼承來(lái)的方法。
那么,,是不是就沒有辦法了呢,?不是的!我們可以使用jdk中的javap命令來(lái)突破這個(gè)問題:
java -private Exam ; -private 標(biāo)志表示所有的成員都應(yīng)該顯示,,甚至包括私有成員
運(yùn)行結(jié)果如下:
此時(shí),,可以看到類中所有的屬性、方法都有了,。
3.調(diào)用Method及Field類中的相關(guān)方法獲取private聲明的屬性及方法
也許你還在為第二步中如此辛苦地得到類中的信息相當(dāng)不解,,其實(shí)這是在為這一步作鋪墊。請(qǐng)看以下代碼:Testo2.java
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
-
- public class Test02 {
- public static void main(String args[]){
- Exam e=new Exam();
- try {
- field1 = e.getClass().getDeclaredField("field1");
- field2 = e.getClass().getDeclaredField("field2");
- field1.setAccessible(true);
- System.out.println("field1: "+field1.get(e));
- field1.set(e,"重新設(shè)置一個(gè)field1值");
- System.out.println("field1: "+field1.get(e));
- System.out.println("field2: "+field2.get(e));
- field2.set(e,"重新設(shè)置一個(gè)field2值");
- System.out.println("field2: "+field2.get(e));
- } catch (NoSuchFieldException e1) {
- e1.printStackTrace();
- }catch (IllegalArgumentException e1) {
- e1.printStackTrace();
- } catch (IllegalAccessException e1) {
- e1.printStackTrace();
- }
-
- try {
-
- Method method1 = e.getClass().getDeclaredMethod("fun1");
- method1.invoke(e);
-
- Method method2 = e.getClass().getDeclaredMethod("fun2");
- method2.setAccessible(true);
- method2.invoke(e);
-
- Method method3 = e.getClass().getDeclaredMethod("fun3",String.class);
- method3.setAccessible(true);
- method3.invoke(e,"fun3的參數(shù)");
- } catch (NoSuchMethodException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- } catch (SecurityException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }catch (IllegalAccessException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- } catch (IllegalArgumentException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- } catch (InvocationTargetException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- }
- }
注意以下語(yǔ)句:
- field1 = e.getClass().getDeclaredField("field1");
getDeclaredField(String fieldName)中,,參數(shù)fieldName為屬性名,,
- Method method3 = e.getClass().getDeclaredMethod("fun3",String.class);
getDeclaredMethod(String methodName,Class parameterType)中,第一個(gè)參數(shù)為方法名,,第二個(gè)參數(shù)為方法參數(shù)類型,,當(dāng)然在此方法中第二個(gè)參數(shù)為可孌參數(shù)。
Test02.java運(yùn)行結(jié)果如下:
由運(yùn)行結(jié)果可知,,利用反射不但可以訪問類的私有屬性,、方法,還可以重新設(shè)置私有屬性的值,,調(diào)用私有方法,。
|