本篇文章為在工作中使用JAVA反射的經(jīng)驗(yàn)總結(jié),也可以說是一些小技巧,以后學(xué)會(huì)新的小技巧,會(huì)不斷更新。
在開始之前,我先定義一個(gè)測(cè)試類Student,代碼如下:
- package chb.test.reflect;
-
- public class Student {
- private int age;
- private String name;
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
-
- public static void hi(int age,String name){
- System.out.println("大家好,我叫"+name+",今年"+age+"歲");
- }
- }<PRE></PRE>
package chb.test.reflect;
public class Student {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void hi(int age,String name){
System.out.println("大家好,我叫"+name+",今年"+age+"歲");
}
}
一、JAVA反射的常規(guī)使用步驟
反射調(diào)用一般分為3個(gè)步驟:
代碼示例:
- Class cls = Class.forName("chb.test.reflect.Student");
- Method m = cls.getDeclaredMethod("hi",new Class[]{int.class,String.class});
- m.invoke(cls.newInstance(),20,"chb");<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Method m = cls.getDeclaredMethod("hi",new Class[]{int.class,String.class});
m.invoke(cls.newInstance(),20,"chb");
二、方法調(diào)用中的參數(shù)類型
在方法調(diào)用中,參數(shù)類型必須正確,這里需要注意的是不能使用包裝類替換基本類型,比如不能使用Integer.class代替int.class。
如我要調(diào)用Student的setAge方法,下面的調(diào)用是正確的:
- Class cls = Class.forName("chb.test.reflect.Student");
- Method setMethod = cls.getDeclaredMethod("setAge",int.class);
- setMethod.invoke(cls.newInstance(), 15);<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Method setMethod = cls.getDeclaredMethod("setAge",int.class);
setMethod.invoke(cls.newInstance(), 15);
而如果我們用Integer.class替代int.class就會(huì)出錯(cuò),如:
- Class cls = Class.forName("chb.test.reflect.Student");
- Method setMethod = cls.getDeclaredMethod("setAge",Integer.class);
- setMethod.invoke(cls.newInstance(), 15);<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Method setMethod = cls.getDeclaredMethod("setAge",Integer.class);
setMethod.invoke(cls.newInstance(), 15);
jvm會(huì)報(bào)出如下異常:
- java.lang.NoSuchMethodException: chb.test.reflect.Student.setAge(java.lang.Integer)
- at java.lang.Class.getDeclaredMethod(Unknown Source)
- at chb.test.reflect.TestClass.testReflect(TestClass.java:23)<PRE></PRE>
java.lang.NoSuchMethodException: chb.test.reflect.Student.setAge(java.lang.Integer)
at java.lang.Class.getDeclaredMethod(Unknown Source)
at chb.test.reflect.TestClass.testReflect(TestClass.java:23)
三、static方法的反射調(diào)用
static方法調(diào)用時(shí),不必得到對(duì)象示例,如下:
- Class cls = Class.forName("chb.test.reflect.Student");
- Method staticMethod = cls.getDeclaredMethod("hi",int.class,String.class);
- staticMethod.invoke(cls,20,"chb");
-
Class cls = Class.forName("chb.test.reflect.Student");
Method staticMethod = cls.getDeclaredMethod("hi",int.class,String.class);
staticMethod.invoke(cls,20,"chb");//這里不需要newInstance
//staticMethod.invoke(cls.newInstance(),20,"chb");
四、private的成員變量賦值
如果直接通過反射給類的private成員變量賦值,是不允許的,這時(shí)我們可以通過setAccessible方法解決。代碼示例:
- Class cls = Class.forName("chb.test.reflect.Student");
- Object student = cls.newInstance();
- Field field = cls.getDeclaredField("age");
- field.set(student, 10);
- System.out.println(field.get(student));<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();//得到一個(gè)實(shí)例
Field field = cls.getDeclaredField("age");
field.set(student, 10);
System.out.println(field.get(student));
運(yùn)行如上代碼,系統(tǒng)會(huì)報(bào)出如下異常:
- java.lang.IllegalAccessException: Class chb.test.reflect.TestClass can not access a member of class chb.test.reflect.Student with modifiers "private"
- at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
- at java.lang.reflect.Field.doSecurityCheck(Unknown Source)
- at java.lang.reflect.Field.getFieldAccessor(Unknown Source)
- at java.lang.reflect.Field.set(Unknown Source)
- at chb.test.reflect.TestClass.testReflect(TestClass.java:20)<PRE></PRE>
java.lang.IllegalAccessException: Class chb.test.reflect.TestClass can not access a member of class chb.test.reflect.Student with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.reflect.Field.doSecurityCheck(Unknown Source)
at java.lang.reflect.Field.getFieldAccessor(Unknown Source)
at java.lang.reflect.Field.set(Unknown Source)
at chb.test.reflect.TestClass.testReflect(TestClass.java:20)
解決方法:
- Class cls = Class.forName("chb.test.reflect.Student");
- Object student = cls.newInstance();
- Field field = cls.getDeclaredField("age");
- field.setAccessible(true);
- field.set(student, 10);
- System.out.println(field.get(student));<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();
Field field = cls.getDeclaredField("age");
field.setAccessible(true);//設(shè)置允許訪問
field.set(student, 10);
System.out.println(field.get(student));
其實(shí),在某些場合下(類中有g(shù)et,set方法),可以先反射調(diào)用set方法,再反射調(diào)用get方法達(dá)到如上效果,代碼示例:
- Class cls = Class.forName("chb.test.reflect.Student");
- Object student = cls.newInstance();
-
- Method setMethod = cls.getDeclaredMethod("setAge",Integer.class);
- setMethod.invoke(student, 15);
-
- Method getMethod = cls.getDeclaredMethod("getAge");
- System.out.println(getMethod.invoke(student));