Java反射机制可以动态修改实例中final修饰的成员变量吗?

(转自:https://www.cnblogs.com/damonhuang/p/5421563.html 侵删)

问题:Java反射机制可以动态修改实例中final修饰的成员变量吗?

回答是分两种情况的。

1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了。

2. 当final修饰的成员变量在定义的时候并没有初始化值的话,那么就还能通过java反射机制来动态修改它的值。

 

实验:

1. 当final修饰的成员变量在定义的时候就初始化了值

1 public Class Person {
2      private final String name = "damon.huang";
3      public String getName() {
4           return this.name;
5      }
6 }
复制代码
 1 import java.lang.reflect.Field;
 2 
 3 /**
 4  * @author damon.huang
 5  *
 6  */
 7 public class TestReflect {
 8 
 9     public static void main(final String[] args) {
10         final Person p = new Person();
11         System.out.println("原始值:" + p.getName());
12         System.out.println("--------separate----------");
13         changePorperty(p);
14     }
15 
16     public static void changePorperty(final Person p) {
17         final Class<?> clz = p.getClass();
18         try {
19             final Field nameField = clz.getDeclaredField("name");
20             nameField.setAccessible(true);
21             nameField.set(p, String.valueOf("huang.damon"));
22             System.out.println("反射机制修改后的Field实例的值:" + nameField.get(p));
23             System.out.println("反射机制修改后的Person实例的值:" + p.getName());
24             System.out.println("--------separate----------");
25         } catch (final NoSuchFieldException e) {
26             e.printStackTrace();
27         } catch (final SecurityException e) {
28             e.printStackTrace();
29         } catch (final IllegalArgumentException e) {
30             e.printStackTrace();
31         } catch (final IllegalAccessException e) {
32             e.printStackTrace();
33         }
34     }
35 }
复制代码

结果如下:

原始值:damon.huang
--------separate----------
反射机制修改后的Field实例的值nameField.get(p):huang.damon
反射机制修改后的Person实例的值p.getName():damon.huang
--------separate----------

为什么p.getName()的值没有被修改掉呢,这是因为

编译期间final类型的数据自动被优化了,即:所有用到该变量的地方都被替换成了常量。所以 get方法在编译后自动优化成了return "damon.huang"; 而不是 return this.name;

可以通过String name = (null!=null?"ddd":"damon.huang");来阻止编译时的自动优化。refere to: 答案引用这是的结果就会看到变量值被动态修改了

原始值:damon.huang
--------separate----------
反射机制修改后的Field实例的值:huang.damon
反射机制修改后的Person实例的值:huang.damon
--------separate----------

 

2.当final修饰的成员变量在定义的时候并没有初始化值的话

复制代码
 1 public class Person {
 2     private final String name;
 3 
 4     public Person() {
 5         this.name = "damon.huang";
 6     }
 7 
 8     public String getName() {
 9         return this.name;
10     }
11 }
复制代码
原始值:damon.huang
--------separate----------
反射机制修改后的Field实例的值:huang.damon
反射机制修改后的Person实例的值:huang.damon
--------separate----------

结果是final修饰的成员变量值被动态修改了

猜你喜欢

转载自blog.csdn.net/weixin_41704428/article/details/80494808