使用反射更改字符串的效果

ami*_*mit 12 java jvm immutability

众所周知,String在java中是不可变的.但是,可以通过获取Field并设置访问级别来使用反射来更改它.(我知道这是未经修改的,我不打算这样做,这个问题纯粹是理论上的).

我的问题:假设我知道我在做什么(并根据需要修改所有字段),程序是否正常运行?或者jvm是否进行了一些依赖于String不可变的优化?我会遭受性能损失吗?如果是这样,它会做出什么假设?该计划会出现什么问题

ps String只是一个例子,除了示例之外,我实际上对一般答案感兴趣.

谢谢!

Dan*_*Tao 6

如果你这样做的话,你肯定是在自找麻烦。这是否意味着您肯定会立即看到错误?不会。在很多情况下,你可能会侥幸逃脱惩罚,具体取决于你在做什么。

以下是它会咬你的几种情况:

  • 您修改了恰好在代码中某处声明为文字的字符串。例如,你有一个function并且在某个地方它被称为像function("Bob");在这种情况下,字符串会在整个应用程序中"Bob"发生更改(声明为 的字符串常量也是如此)。final
  • 您可以修改在子字符串操作中使用的字符串,或者子字符串操作的结果。在Java中,获取字符串的子字符串实际上使用与源字符串相同的底层字符数组,这意味着对源字符串的修改将影响子字符串(反之亦然)。
  • 您修改了一个恰好在某个映射中用作键的字符串。它不再与其原始值进行比较,因此查找将失败。

我知道这个问题是关于 Java 的,但我不久前写了一篇博客文章,说明了如果您在 .NET 中改变字符串,您的程序可能会表现得多么疯狂。情况确实很相似。


Ser*_*rov 6

编译后,一些字符串可能会引用一个实例,因此,您将编辑超出您想要的内容,并且永远不知道您还在编辑其他内容.

public static void main(String args[]) throws Exception {
    String s1 = "Hello"; // I want to edit it
    String s2 = "Hello"; // It may be anywhere and must not be edited
    Field f = String.class.getDeclaredField("value");
    f.setAccessible(true);
    f.set(s1, "Doesn't say hello".toCharArray());
    System.out.println(s2);
}
Run Code Online (Sandbox Code Playgroud)

输出:

Doesn't say hello
Run Code Online (Sandbox Code Playgroud)