镇江网站开发,庆阳西峰,html所有标签大全,聊天软件开发需要多少钱当final修饰一个数据域时#xff0c;意义是声明该数据域是最终的#xff0c;不可修改的。常见的使用场景就是eclipse自动生成的serialVersionUID一般都是final的。 另外还可以构造线程安全#xff08;thread safe#xff09;的immutable类#xff0c;比如String#xff0… 当final修饰一个数据域时意义是声明该数据域是最终的不可修改的。常见的使用场景就是eclipse自动生成的serialVersionUID一般都是final的。 另外还可以构造线程安全thread safe的immutable类比如String其数据域都是final的。这些使用场景都建立在final不可修改这个条件上但是反射可以打破这一切。 1.利用反射修改final数据域 首先构造一个Person类里面有个final字段NAME。我们尝试着修改这个字段。顺利的出乎意料。 public class Person {public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {Person p new Person();Field field p.getClass().getDeclaredField(NAME);field.setAccessible(true);field.set(p,Hello);System.out.println(field.get(p));//p.printName();}private final String NAME Clive;public Person() {}public void printName() {System.out.println(NAME);}
}
/***************
console print:
Hello
***************/ 2.内联与内联消除 NAME数据域如此简单的就被修改了final真是太不安全了 但是当我们调用p.printName() 时控制台打印的却是Clive字符串。这是因为JVM做了优化处理 当一个数据域被final修饰,那就表明这个数据域是常量JVM会把所有NAME数据域出现的地方全部用Clive替换掉 比如 printName() 方法其实被优化成了这样。 public void printName() { System.out.println(Clive); } 所以要想不被自动优化就要把代码弄得复杂点如下 public class Person {public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {Person p new Person();Field field p.getClass().getDeclaredField(NAME);field.setAccessible(true);field.set(p,Hello);System.out.println(field.get(p));p.printName();}private final String NAME (null!null?Clive:Clive); //声明时即初始化public Person() {//或者在这里设置NAME数据域的值//NAMEClive;}public void printName() {System.out.println(NAME);}
}
/***************
console print:
Hello
Hello
***************/ 结果见 console print,顺利消除了优化,final字段最终被修改了! 3.修改static final数据域 如果在NAME字段再增加一个static关键字修饰然后再用反射修改的话就不行了 会抛出异常 java.lang.IllegalAccessException: Can not set static final int field ... 这时修改Field中的modifiers数据域清除代表final的那个bit才可以成功修改。 public class Person {public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {Person p new Person();Field field p.getClass().getDeclaredField(NAME);Field modifiers field.getClass().getDeclaredField(modifiers);modifiers.setAccessible(true);modifiers.setInt(field, field.getModifiers() ~Modifier.FINAL);//fianl标志位置0field.set(p,Hello);System.out.println(field.get(p));p.printName();}private final String NAME (null!null?Clive:Clive);public Person() {}public void printName() {System.out.println(NAME);}
}
/**************
console print:
Hello
Hello
**************/ 总结 这个知识点感觉知道就好平时还是不要修改final数据域的好 :) 引用 1.https://www.oschina.net/question/1245392_159103 2.https://github.com/jOOQ/jOOR 转载于:https://www.cnblogs.com/fudashi/p/6624379.html