先来看一个通过反射来动态给变量赋值的:
package com.reflect.demo;
public class Student {
public String name;
public Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
}
}
package com.reflect.demo;
import java.lang.reflect.Field;
public class BaseTest {
public static void main(String[] args) throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Student stu1 = new Student();
Field nameField1 = Student.class.getField("name");
nameField1.set(stu1, "张三");
System.out.println("学生1的姓名为:" + stu1.getName() + " \t 年龄为:"
+ stu1.getAge());
}
}
通过反射机制来实现在程序运行中动态给变量赋值,需要考虑以下几点:
1)如何获取相应的Filed,Method对象?
2)怎样将动态的值设置到目标对象?
3)碰到私有域变量Field和方法Method如何处理?
对于第一点,主要是获取Class对象。有三种方法获取Class对象
a. 类名.class b. 对象名.getClass() 例如用stu1.getClass()代替 Student.class结果完全一样
c. Class.forName("类名");
对于第二点,代码nameField1.set(stu1, "张三");是关键,第一个参数即为目标对象。亦即通过Field对象的
set方法给对象stu1的name属性赋值。
对于第三点,若要给age赋值,但age在Student类中是私有变量,是不容许外部类访问的。这时候想起上一章节中
提到的抽象类AccessibleObject提供了setAccessible方法,该方法可以跳过Java 语言访问控制检查。
代码如下:
Student stu1 = new Student();
Student stu2 = new Student();
Field nameField1 = stu1.getClass().getField("name");
nameField1.set(stu1, "张三");
System.out.println("学生1的姓名为:"+stu1.getName()+" \t 年龄为:"+stu1.getAge());
Field ageField2 = stu2.getClass().getDeclaredField("age");
ageField2.setAccessible(true);
ageField2.set(stu2, 18);
System.out.println("学生2的姓名为:"+stu2.getName()+" \t 年龄为:"+stu2.getAge());
还有得注意的是:
1)、注意getField与getDeclaredField的区别:两者都是java.lang.Class类提供的方法,前者用于取指定类或接口的公有属性,而age是私有属性必须用后者来获取。
2)、在此不能用ageField2.setInt(stu2,18)代替ageField2.set(stu2, 18),这里做了严格的校验,Student中age属性采用了Integer类型。