Java字符串真的是不可变的吗?我们都知道StringJava 中是不可变的,但请检查以下代码:String s1 = "Hello World"; String s2 = "Hello World"; String s3 = s1.substring(6); System.out.println(s1); // Hello World System.out.println(s2); // Hello World System.out.println(s3); // World Field field = String.class.getDeclaredField("value"); field.setAccessible(true); char[] value = (char[])field.get(s1); value[6] = 'J'; value[7] = 'a'; value[8] = 'v'; value[9] = 'a'; value[10] = '!'; System.out.println(s1); // Hello Java! System.out.println(s2); // Hello Java! System.out.println(s3); // World 为什么这个程序运行这样?为什么价值s1和s2变化,但不是s3?
3 回答
繁星点点滴滴
TA贡献1803条经验 获得超3个赞
在Java中,如果将两个字符串原语变量初始化为同一个字面值,则会为这两个变量分配相同的引用:
String Test1="Hello World";String Test2="Hello World";System.out.println(test1==test2); // true
这就是比较返回true的原因。创建第三个字符串,使用substring()
该字符串创建一个新字符串而不是指向相同的字符串。
使用反射访问字符串时,您将获得实际指针:
Field field = String.class.getDeclaredField("value");field.setAccessible(true);
因此,更改为将更改包含指向它的指针的字符串,但由于s3
它创建的新字符串substring()
不会更改。
蝴蝶刀刀
TA贡献1801条经验 获得超8个赞
你正在使用反射来规避String的不变性 - 它是一种“攻击”形式。
你可以创建很多像这样的例子(例如你甚至可以实例化一个Void
对象),但这并不意味着String不是“不可变的”。
有些用例可能会使用这种类型的代码,并且可以“良好编码”,例如尽早清除内存中的密码(GC之前)。
根据安全管理器的不同,您可能无法执行代码。
添加回答
举报
0/150
提交
取消