Java拾贝第十八天——反射之使用反射修改属性
在认识反射相关类中,可以通过Class类的方法来获取一个Filed类访问一个类的属性。当然也提供了直接通过Field类修改属性。
Filed类常用方法如下:
方法 | 类型 | 描述 |
---|---|---|
public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException | 普通方法 | 获取某实例的属性值 |
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException | 普通方法 | 设置某实例的属性值 |
public boolean isAccessible() | 普通方法 | 能否被外部直接访问 |
public void setAccessible(boolean flag) throws SecurityException | 普通方法 | 设置能否被外部直接访问 |
public Object get(Object obj)
获取某实例的属性值
栗子:
package moudle2;
import java.lang.reflect.Field;
public class Test18 {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("moudle2.P");//通过反射获取P类对象
Field field = clazz.getField("x");//通过反射获取公开x属性对象
Object instance = clazz.newInstance();//创建P类实例
System.out.println(field.get(instance));//等价于 System.out.println(instance.i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class P{
public double x = 20;
}
程序运行结果:
20.0
注意上述栗子中field指向的是P类中的x属性。
再次强调反射就是在运行过程中可以知晓任意类的任意信息。
public void set(Object obj, Object value)
设置某实例的属性值
栗子:
package moudle2;
import java.lang.reflect.Field;
public class Test18 {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("moudle2.P");
Field field = clazz.getField("x");//通过反射获取公开x属性对象
Object instance = clazz.newInstance();//创建P类实例
field.set(instance,49.99);//通过反射设置属性值 等价于 instance.x=49.99
System.out.println(field.get(instance));
} catch (Exception e) {
e.printStackTrace();
}
}
}
class P{
public double x = 20;
}
程序运行结果:
49.99
反射真的太神奇辣!
可上述两个栗子都直接访问的属性,这并不符合封装性。
至此,其他两个方法登场!
public boolean isAccessible()
属性能否被外部直接访问
栗子:
package moudle2;
import java.lang.reflect.Field;
public class Test18 {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("moudle2.P");
//clazz.getField("i");私有属性无法被getField()方法获取
Field field = clazz.getDeclaredField("i");//通过反射获取公开i属性对象
if (field.isAccessible()){
System.out.println("该属性可以被直接访问");
}else {
System.out.println("该属性无法被直接访问");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class P{
public double x = 20;
private int i = 10;
}
程序运行结果:
该属性无法被直接访问
public void setAccessible(boolean flag)
设置属性能否被外部直接访问
栗子:
package moudle2;
import java.lang.reflect.Field;
public class Test18 {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("moudle2.P");
Object o = clazz.newInstance();
Field field = clazz.getDeclaredField("i");//通过反射获取公开x属性对象
field.setAccessible(true);//设置可以被外部直接访问
System.out.println("i属性值"+field.get(o));
field.set(o,50);
System.out.println("set后 i属性值"+field.get(o));
} catch (Exception e) {
e.printStackTrace();
}
}
}
class P{
public double x = 20;
private int i = 10;
}
程序运行结果:
i属性值10
set后 i属性值50
虽然修改成功了,但这种形式的修改属性破坏了封装性。
开发中不要直接操作属性!!!还是使用setter和getter最优。