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

发布于 2024-12-10 23:55:48 字数 342 浏览 0 评论 0 原文

我记得读过一个章节,可能是在 Bloch 的 Effective Java 中,其中提到对于大多数情况,

String a = "fish";
String b = "fish";

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

我浏览了 Bloch 关于 equals()、不变性和对象创建的章节,但找不到我记得的这一点!撕扯我的头发,有人记得在哪里描述这是为什么吗?它甚至可能不在 EJ 中,但我想找到它。提示:这在哪里解释是我的实际问题。

I remember reading a section, possibly in Bloch's Effective Java, that said that for most cases, where

String a = "fish";
String b = "fish";

that a == b in most cases because Strings are immutable. But that due to temporary construction of objects or some such, new String("fish") would yield a distinct object reference.

I looked through Bloch chapters on equals(), immutability, and object creation, but cannot find this bit I remember!! Tearing my hair out, does anyone remember where is the description of why this is? It may not even be in EJ but I'd like to find it. Hint: where is this explained is my actual question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

回忆躺在深渊里 2024-12-17 23:55:48

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

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

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

有两件事要记住:

  • 永远不要使用 new String("something")
  • 总是将字符串与 equals(..) 进行比较(除非您真的知道自己在做什么,并记录下来)

It's not related to immutability. It's the way strings are handled by the JVM. A string literal with the same contents represents the same object ("string literal" means roughly "text surrounded by quotes"). There is a table of string objects in the JVM, and each string literal has exactly one object in that table.

However, when you expicitly create a new instance, you construct a new string object based on the string object taken from the table.

From any string formed by not using a literal (but by calling toString(), by instantiating, etc.) you can get the object from the jvm table by calling str.intern(). The intern() method returns exactly one instance for each character sequence that exists. new String("fish").intern() will return the same instance as simply String s = "fish"

There are two things to remember:

  • never use new String("something")
  • always compare strings with equals(..) (unless you really know what you are doing, and document it)
想念有你 2024-12-17 23:55:48

我认为您正在寻找 String .intern() 方法,维护常量字符串池。

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

编译器将查看 String a = "fish" 和 String b = "fish",然后可能会也可能不会指向相同的地址。但是,如果你执行 a.intern(); b.intern() 那么它可能会将它们放在同一个字符串池中并且 a == b。

I think you are looking for String.intern() method which maintains a constant string pool.

The operator '==' compares object references (addresses) while .equals() is a method call which looks at semantic equivalence.

The compiler will look at String a = "fish" and String b = "fish" and then may or may not point to the same address. However, if you do a.intern(); b.intern() then it will probably put them in the same string pool and a == b.

夏尔 2024-12-17 23:55:48

如果您正在寻找明确的描述,那么请转到定义: JLS § 3.10.5 字符串文字

您应该熟悉的示例代码是:

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

包testPackage;
类测试{
        公共静态无效主(字符串[] args){
                字符串 hello =“你好”,lo =“lo”;
                System.out.print((hello == "你好") + " ");
                System.out.print((Other.hello == hello) + " ");
                System.out.print((other.Other.hello == 你好) + " ");
                System.out.print((hello == ("Hel"+"lo")) + " ");
                System.out.print((hello == ("Hel"+lo)) + " ");
                System.out.println(hello == ("Hel"+lo).intern());
        }
}
类其他{静态字符串hello =“你好”; }

和编译单元:

封装其他;
公共类其他{静态字符串hello =“你好”; }

产生输出:

true true true true false true

If you're looking for a definitive description, well, go to the definition: JLS § 3.10.5 String Literals.

The example code you should be familiar with is,

Thus, the test program consisting of the compilation unit (§7.3):

package testPackage;
class Test {
        public static void main(String[] args) {
                String hello = "Hello", lo = "lo";
                System.out.print((hello == "Hello") + " ");
                System.out.print((Other.hello == hello) + " ");
                System.out.print((other.Other.hello == hello) + " ");
                System.out.print((hello == ("Hel"+"lo")) + " ");
                System.out.print((hello == ("Hel"+lo)) + " ");
                System.out.println(hello == ("Hel"+lo).intern());
        }
}
class Other { static String hello = "Hello"; }

and the compilation unit:

package other;
public class Other { static String hello = "Hello"; }

produces the output:

true true true true false true
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文