Java 为什么是不可变的新字符串(“鱼”)!=新字符串(“鱼”)?

Java 为什么是不可变的新字符串(“鱼”)!=新字符串(“鱼”)?,java,immutability,puzzle,effective-java,Java,Immutability,Puzzle,Effective Java,我记得读过一节,可能是在布洛赫的《高效Java》中,其中说在大多数情况下 String a = "fish"; String b = "fish"; 在大多数情况下a==b,因为字符串是不可变的。但是,由于对象或类似对象的临时构造,新字符串(“fish”)将产生一个不同的对象引用 我浏览了布洛赫关于equals()、不变性和对象创建的章节,但找不到我记得的这一点!!把我的头发扯下来,有人记得这是怎么回事吗?它甚至可能不在EJ中,但我想找到它。提示:这里解释的是我的实际问题。这与不变性无关。这是

我记得读过一节,可能是在布洛赫的《高效Java》中,其中说在大多数情况下

String a = "fish";
String b = "fish";
在大多数情况下a==b,因为字符串是不可变的。但是,由于对象或类似对象的临时构造,新字符串(“fish”)将产生一个不同的对象引用


我浏览了布洛赫关于equals()、不变性和对象创建的章节,但找不到我记得的这一点!!把我的头发扯下来,有人记得这是怎么回事吗?它甚至可能不在EJ中,但我想找到它。提示:这里解释的是我的实际问题。

这与不变性无关。这是JVM处理字符串的方式。具有相同内容的字符串文字表示相同的对象(“字符串文字”大致表示“由引号包围的文本”)。JVM中有一个字符串对象表,每个字符串文本在该表中只有一个对象

但是,当您明确地创建一个新实例时,您将基于从表中获取的string对象构造一个新的string对象

通过调用
str.intern()
,可以从不使用文本(而是通过调用toString()、通过实例化等)形成的任何字符串中获得jvm表中的对象。
intern()
方法只为存在的每个字符序列返回一个实例
newstring(“fish”).intern()
将返回与single
String s=“fish”相同的实例

有两件事需要记住:

  • 切勿使用新字符串(“某物”)
  • 始终将字符串与
    相等(..)
    进行比较(除非您确实知道自己在做什么,并记录下来)

  • 我认为您正在寻找一种维护常量字符串池的方法

    运算符“==”比较对象引用(地址),而.equals()是一个方法调用,用于查看语义等价性


    编译器将查看字符串a=“fish”和字符串b=“fish”,然后可能指向也可能不指向同一地址。但是,如果你做了一个实习生();b、 intern()则它可能会将它们放在同一个字符串池中,并且a==b.

    如果您要查找确定的描述,那么请转到定义:

    您应该熟悉的示例代码是

    因此,由编译单元组成的测试程序(§7.3):

    及编制组:

    package other;
    public class Other { static String hello = "Hello"; }
    
    生成输出:

    true true true true false true
    

    相关的:相关的:谢谢,我会看看这些之后;当我提交时,我没有看到任何看起来相同的标题,但我确实看到了!请注意,
    intern()
    会将字符串放在表中,如果它不在表中。这是垃圾收集器无法恢复的perm gen空间。在使用内存分析器并找到在运行时插入某些内容的真正原因之前,应用程序代码应该很少插入任何内容。@Bozho虽然您在“永不使用
    新字符串(“某些内容”)
    ”这一点上说得很对,但类似
    字符串s=hey.retrieveMeThatString()的代码;s=新字符串可以在生产代码中找到,在某些情况下甚至有意义。@alf-在什么情况下?对不可变对象进行“防御性复制”是没有意义的。@Bozho内存再次出现。如果您查看
    “一个很长的字符串”。子字符串(6,11)
    ,您将看到它的
    字段包含整个原始数组,
    [a,v,e,r,y,l,o,n,g,s,t,r,i,n,g]
    。如果你收到的是为了长时间使用部件而拆开的巨大字符串,你就不想保留原来的对象。事实上,请参见并感谢两位使用intern()方法,我没有研究过这个问题。
    true true true true false true