Java反射机制可以动态修改实例中final修饰的成员变量吗?
问题: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修饰的成员变量值被动态修改了