2
public class First
{
    public static void main(String[] args)
    {
        String str1="Hello ",str2="World",str3="Hello World";
        System.out.println(str3==("Hello "+"World")); //Prints true
        System.out.println(str3==("Hello "+str2));  //Prints false
    }
}

上述原因在JLS-中给出

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

• 在运行时通过连接计算的字符串是新创建的,因此是不同的。

我想问的是-为什么在运行时计算的字符串与在编译时计算的字符串不同?是因为内存分配,一个是在堆中分配内存,一个是在字符串池中分配内存还是有其他原因?请澄清。

4

4 回答 4

2

编译器不知道str2包含什么,因为它必须执行代码才能知道str2当您将它与“Hello”连接时的内容(它可以进行一些优化并内联它,因为它不会改变,但它不会不要这样做)。

想象一个更复杂的场景,str2用户输入的内容。即使用户输入了“World”,编译器也无法知道这一点。

因此,它无法使用分配给并在第一次比较中使用的常量池中str3 == "Hello World"的相同 内容执行比较。"Hello World"str3

因此编译器将通过 using 生成连接,StringBuilder并最终创建另一个Stringwith value Hello World,因此身份比较将失败,因为一个对象是来自常量池的对象,而另一个对象是刚刚创建的对象。

于 2015-07-09T06:00:29.937 回答
1

您应该equals在比较时使用Objects而不是==运算符。

于 2015-07-09T05:33:02.380 回答
0

编译器认识到常量不会改变,如果您使用 + 运算符,会将它们连接到编译的代码中。这就是为什么在第一种情况下它将运行执行,str3==("HelloWorld")因为“Helloworld”文字已经存在于字符串池中,它们都将指向字符串池中的相同位置,它将打印 true 。

在这种情况下str3==("Hello"+str2),编译器不会检查 str2 是否World在其中,它会将其视为可以具有任何值的变量,因此在运行时他们将创建一个新的字符串变量,该变量指向与字符串池中的HelloWorld不同str3,所以它会打印错误。

于 2019-06-28T12:52:57.480 回答
0

字符串在 Java 中是不可变的。因此,当您连接两个字符串时,会在运行时创建第三个字符串来表示连接后的值。因此,使用 == 返回 false,因为两个参数都指向 String 对象的不同实例。

对于编译时场景,由于编译器优化,已经创建了连接字符串,并且在运行时,== 的两个参数都由相同的实例表示。因此,== 返回 true,因为两个参数都指向同一个实例(引用)。

于 2015-07-09T05:38:42.607 回答