几乎所有人都知道Java中的字符串是不可变的。最近我发现了一些东西,可能表明这并不总是正确的。让我们来试试这段代码:
System.out.println("-------- BEFORE MODIFICATIONS --------");
String beforeTest = new String("Original");
System.out.println(beforeTest);
java.lang.reflect.Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.set("Original", "Modified".toCharArray());
System.out.println("-------- AFTER MODIFICATIONS --------");
System.out.println(beforeTest);
System.out.println("Original");
String test = new String("Original");
System.out.println(test);
String test2 = new String("Original 2");
System.out.println(test2);
输出将为:
-------- BEFORE MODIFICATIONS --------
Original
-------- AFTER MODIFICATIONS --------
Original
Modified
Modified
Original 2
这个技巧是如何工作的?JVM是如何知道哪些对象应该被更改,哪些不应该被更改的?这个技巧背后有什么机制?为什么已经创建的beforeTest
字符串没有被更改?这个技巧是否真的违反了字符串是不可变的
原则?
setAccessible
违反了private
时,核心类不变式才会失效。 - Mike Samuel