10

问题归结为这段代码:

// setup
String str1 = "some string";
String str2 = new String(str1);
assert str1.equals(str2);
assert str1 != str2;
String str3 = str2.intern();

// question cases
boolean case1 = str1 == "some string";
boolean case2 = str1 == str3;

Java 标准是否对和的值提供任何保证?当然,链接到 Java 规范的相关部分会很好。case1case2

是的,我查看了 SO 找到的所有“类似问题”,但没有发现重复项,因为我发现没有人以这种方式回答了这个问题。不,这不是关于通过替换来“优化”字符串比较的错误equals想法==

4

2 回答 2

14

这是您的 JLS 报价,第 3.10.5 节

每个字符串文字都是对 String 类(第 4.3.3 节)实例(第 4.3.1 节、第 12.5 节)的引用(第 4.3 节)。字符串对象有一个常量值。字符串字面量——或者更一般地,作为常量表达式值的字符串(第 15.28 节)——是“内部的”,以便使用 String.intern 方法共享唯一的实例。

因此,由编译单元(§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"; }

和编译单元:

package other;

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

产生输出: true true true true false true

这个例子说明了六点:

同一包 (§7) 中同一类 (§8) 中的文字字符串表示对同一 String 对象 (§4.3.1) 的引用。

同一包中不同类中的文字字符串表示对同一 String 对象的引用。

不同包中不同类中的文字字符串同样表示对同一 String 对象的引用。

由常量表达式(第 15.28 节)计算的字符串在编译时计算,然后将其视为文字。

在运行时通过连接计算的字符串是新创建的,因此是不同的。显式实习计算字符串的结果是与任何具有相同内容的预先存在的文字字符串相同的字符串。

结合实习生的JavaDoc,您有足够的信息来推断您的两个案例都将返回 true。

于 2013-01-23T07:43:51.103 回答
6

我认为 String.intern API 提供了足够的信息

一个字符串池,最初是空的,由 String 类私下维护。

当调用 intern 方法时,如果池中已经包含一个等于该 String 对象的字符串,由 equals(Object) 方法确定,则返回池中的字符串。否则,将此 String 对象添加到池中并返回对该 String 对象的引用。

由此可见,对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为真时,s.intern() == t.intern() 才为真。

所有文字字符串和字符串值的常量表达式都是实习的。字符串文字在 Java™ 语言规范的第 3.10.5 节中定义。

于 2013-01-23T07:42:11.670 回答