为什么不可变的新String("fish")!= new String("fish")?

orb*_*ish 0 java puzzle immutability effective-java

我记得读过一篇可能在Bloch的Effective Java中的部分,它说大多数情况下,在哪里

String a = "fish";
String b = "fish";
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,a == b因为字符串是不可变的.但是由于临时构造对象或其他一些东西,新的String("fish")会产生一个独特的对象引用.

我通过Bloch章节了解了equals(),不变性和对象创建,但是找不到这一点我记得!! 撕掉我的头发,有没有人记得这是什么原因的描述?它甚至可能不在EJ中,但我想找到它.提示:这解释的是我的实际问题.

Boz*_*zho 10

它与不变性无关.这是JVM处理字符串的方式.具有相同内容的字符串文字表示相同的对象("字符串文字"大致意味着"用引号括起来的文本").JVM中有一个字符串对象表,每个字符串文字在该表中只有一个对象.

但是,当您明确地创建新实例时,您将根据从表中获取的字符串对象构造一个新的字符串对象.

从不使用文字形成的任何字符串(但通过调用toString(),通过实例化等),您可以通过调用从jvm表中获取对象str.intern().该intern()方法只返回存在的每个字符序列的一个实例.new String("fish").intern()将简单地返回相同的实例String s = "fish"

有两件事需要记住:

  • 从不使用 new String("something")
  • 总是比较字符串equals(..)(除非你真的知道你在做什么,并记录它)

  • 再次@Bozho记忆.如果你看一个"非常长的字符串".substring(6,11)`,你会看到它的`value`字段包含整个原始数组,`[a ,, v,e,r,y ,, l,o,n,g,,s,t,r,i,n,g]`.如果为了长时间使用部件而收到大量的琴弦,则不希望保留原始对象. (4认同)
  • @alf - 在什么情况下?制作不可变对象的"防御性副本"毫无意义. (3认同)
  • @Bozho虽然你绝对正确"永远不要使用`new String("something")`,"代码如`String s = hey.retrieveMeThatString(); s = new String(s);`可以在生产代码中找到,在某些情况下甚至是有意义的. (2认同)