Java 为什么是不可变的新字符串(“鱼”)!=新字符串(“鱼”)?
我记得读过一节,可能是在布洛赫的《高效Java》中,其中说在大多数情况下Java 为什么是不可变的新字符串(“鱼”)!=新字符串(“鱼”)?,java,immutability,puzzle,effective-java,Java,Immutability,Puzzle,Effective Java,我记得读过一节,可能是在布洛赫的《高效Java》中,其中说在大多数情况下 String a = "fish"; String b = "fish"; 在大多数情况下a==b,因为字符串是不可变的。但是,由于对象或类似对象的临时构造,新字符串(“fish”)将产生一个不同的对象引用 我浏览了布洛赫关于equals()、不变性和对象创建的章节,但找不到我记得的这一点!!把我的头发扯下来,有人记得这是怎么回事吗?它甚至可能不在EJ中,但我想找到它。提示:这里解释的是我的实际问题。这与不变性无关。这是
String a = "fish";
String b = "fish";
在大多数情况下a==b,因为字符串是不可变的。但是,由于对象或类似对象的临时构造,新字符串(“fish”)将产生一个不同的对象引用
我浏览了布洛赫关于equals()、不变性和对象创建的章节,但找不到我记得的这一点!!把我的头发扯下来,有人记得这是怎么回事吗?它甚至可能不在EJ中,但我想找到它。提示:这里解释的是我的实际问题。这与不变性无关。这是JVM处理字符串的方式。具有相同内容的字符串文字表示相同的对象(“字符串文字”大致表示“由引号包围的文本”)。JVM中有一个字符串对象表,每个字符串文本在该表中只有一个对象 但是,当您明确地创建一个新实例时,您将基于从表中获取的string对象构造一个新的string对象 通过调用
str.intern()
,可以从不使用文本(而是通过调用toString()、通过实例化等)形成的任何字符串中获得jvm表中的对象。intern()
方法只为存在的每个字符序列返回一个实例newstring(“fish”).intern()
将返回与singleString 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