利用java反射机制修改属性值

利用java反射机制修改属性值

本文将介绍如何利用java反射机制修改属性值,废话不多说,直接上代码
1、新建一个实体类,添加属性test以及获取属性值的方法getTest()

public class ReflectTest {
    //测试修改属性
    String test = "修改前的值";
    public String getTest(){
        return test;
    }
}

2、新建一个测试类,利用反射机制获取类对象、方法、属性,方法对象调用invoke()执行方法

class Test{
    public static void main(String[] args) throws Exception {
        //获取ReflectTest类的class对象
        Class<ReflectTest> reflectTestClass = ReflectTest.class;
        //获取实例对象
        ReflectTest reflectTest = reflectTestClass.newInstance();
        //获取属性对象
        Field testField = reflectTestClass.getDeclaredField("test");
        //获取方法对象
        Method getTestMethod = reflectTestClass.getDeclaredMethod("getTest", null);
        //执行方法
        Object invoke = getTestMethod.invoke(reflectTest);
        System.out.println(invoke);
    }
}

修改前得到的打印结果如下
利用java反射机制修改属性值_第1张图片
3、以上为默认修饰符属性未修改的情况,现在我们通过testField.set(reflectTest,“修改后的值”)修改属性值;修改默认属性代码如下:

//获取ReflectTest类的class对象
Class<ReflectTest> reflectTestClass = ReflectTest.class;
//获取实例对象
ReflectTest reflectTest = reflectTestClass.newInstance();
//获取属性对象
Field testField = reflectTestClass.getDeclaredField("test");
//修改属性值
testField.set(reflectTest,"修改后的值");
//获取方法对象
Method getTestMethod = reflectTestClass.getDeclaredMethod("getTest", null);
//执行方法
Object invoke = getTestMethod.invoke(reflectTest);
System.out.println(invoke);

修改后打印结果如下:
利用java反射机制修改属性值_第2张图片
4、默认属性可以修改,那么其他属型呢?我们依次试试public、protected,修改后打印结果均为“修改后的值”。修改private修饰的属性值时却抛出异常IllegalAccessException。原来,在利用反射机制修改私有属性的值前,需要执行setAccessible(true),这样就能绕过private的限制啦,改动代码和结果如下:

//获取属性对象
Field testField = reflectTestClass.getDeclaredField(“test”);
testField.setAccessible(true);
//修改属性值
testField.set(reflectTest,“修改后的值”);

打印结果:
利用java反射机制修改属性值_第3张图片
5、默认、public、protected、private都修改成功了,那么如果都换成静态修饰的呢?小编一一测试之后依然是能够实现的。那么final修饰的属性是否能够被修改呢?
这里首先将属性改为final修饰:

private final String test = “修改前的值”;

修改属性的代码不变:

//获取属性对象
  Field testField = reflectTestClass.getDeclaredField("test");
  testField.setAccessible(true);
  //修改属性值
  testField.set(reflectTest,"修改后的值");
  //获取方法对象
  Method getTestMethod = reflectTestClass.getDeclaredMethod("getTest", null);
  //执行方法
  Object invoke = getTestMethod.invoke(reflectTest);
  System.out.println(invoke);

得到的结果如下,仍然是修改前的值:
利用java反射机制修改属性值_第4张图片
这里可以看见我们打印类的属性值并没有改变,当前反射获取到的属性值却发生了改变,代码和结果如下:

//获取属性对象
  Field testField = reflectTestClass.getDeclaredField("test");
  testField.setAccessible(true);
  //修改属性值
  testField.set(reflectTest,"修改后的值");
  System.out.println(testField.get(reflectTest));

执行以上代码结果如下:
利用java反射机制修改属性值_第5张图片
6、为了修改final修饰的类属性的值,我们要对 Java 反射包中的类进行自我反射。Field 对象有个一个属性叫做 modifiers, 它表示的是属性是否是 public, private, static, final 等修饰的组合。这里把这个 modifiers 也反射出来,进而把 nameField 的 final 约束去掉。代码如下:

//获取ReflectTest类的class对象
Class<ReflectTest> reflectTestClass = ReflectTest.class;
//获取实例对象
ReflectTest reflectTest = reflectTestClass.newInstance();
//获取属性对象
Field testField = reflectTestClass.getDeclaredField("test");
//获取modifiers属性,modifiers属性也是私有的
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
//改掉testField属性的modifiers 值  按位取反再按位与 操作把 final 从修饰集中剔除掉,
// 其他特性如 private, static 保持不变
modifiers.setInt(testField,testField.getModifiers() & ~Modifier.FINAL);
testField.setAccessible(true);
//修改属性值
testField.set(reflectTest,"修改后的值");
//获取方法对象
Method getTestMethod = reflectTestClass.getDeclaredMethod("getTest", null);
//执行方法
Object invoke = getTestMethod.invoke(reflectTest);
System.out.println(invoke);

此时运行程序没有报错,但打印出来的还是修改前的值,原因是编译期间final类型的数据自动被优化,“修改前的值”是直接在常量区内取的值,我们将其换成基本数据类型也是一样,均是取得常量区的值。而使用new String(“修改前的值”)进行初始化编译期间不会被优化:

private final String test = new String(“修改前的值”);

打印结果:
在这里插入图片描述
本期分享就结束啦,楼主是个萌新,初次编写文章,如有不对的地方,欢迎大家留言指正哦。

你可能感兴趣的:(Java基础,java,反射)