在连接两个String s1和s2时,生成的输出String s3将在java中创建堆或常量池吗?

时间:2015-04-02 12:56:00

标签: java string

String S1="He";
String S2="llow";
String S3="Hellow";
String S4="He"+"llow";
String S5=S1+S2;
System.out.println(S3==S4); // prints true
System.out.println(S5==S3); // prints false
System.out.println(S5==S4); // prints false

为什么S5不是从常量池引用对象? 因为S3S4在池中,这就是为什么在S3==S4上给出真的 但是在S5==S3& S5==S4结果为false,表示S5不在池中。

7 个答案:

答案 0 :(得分:5)

字符串s1s4都是编译时常量。

编译器在编译期间计算"He" + "llow",并查询字符串池是否已经存在结果,如果不存在则将其放在那里。

s1 + s2的计算不是在编译时完成的,因此其结果不会被实现。为什么?因为从理论上讲,另一个线程可以更改s1s2的值,所以当我们在代码中获得此指令时,它可能会将s2设置为"foo",结果变为"Hefoo"

作为作者,您可能知道没有线程会这样做,并且这些都是局部变量,但是编译器没有。

如果您将定义更改为:

    final String s1="He";
    final String s2="llow";
    final String s3="Hellow";
    final String s4="He"+"llow";
    final String s5=s1+s2;

然后,s5 == s3的结果确实是true!为什么?因为final关键字让编译器知道这些字符串不会被替换,所以它们是这些变量的 final 值。因此它可以在编译时计算它并获取池中已有的结果。

答案 1 :(得分:2)

来自JLS

https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5

  

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

     

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

对于String S4,你正在进行编译时连接

String S4="He"+"llow";
因此,它指的是与S3相同的对象

但是,S1+S2是运行时的串联,因此,它引用单独的String对象而不是S3,即使S1 + S2S3 有意义的等效 。  即(S1+S2).equals(S3)将返回真实

您可以使用intern方法

将字符串放入池中

答案 2 :(得分:2)

因为在String S4="He"+"llow";对象中创建了池,并且这是与S3="Hellow";相同的编译时常量,它们在池中都是相同的对象,但在运行时在堆中创建S5

答案 3 :(得分:0)

连接的字符串文字输入到字符串池中。但是,由变量串联产生的字符串不是。这就是为什么S3等于S4而不是S5。它们不是指同一个对象。但是,(虽然我还没有对此进行测试)S5.equals(S4)应该返回true。

答案 4 :(得分:0)

System.out.println(S3==S4);//true

因为S4 = "He"+"llow";由编译器优化并导致与" Hellow"相同的字符串。 共享S3,因此S4和S3具有相同的参考。

System.out.println(S5==S3);//false

因为S5和S3是2个具有不同引用的不同对象。

System.out.println(S5==S4);//false

与以前一样。

比较对象时,通常需要比较内容(使用equals()而不是地址/引用(使用==)。

答案 5 :(得分:0)

通常,编译器实例化常量字符串 - 甚至是连接创建的字符串。这就是S3S4是同一个对象的原因。

然而,

S5在运行时被评估,这就是为什么它创建一个新的对象,不同(但等于)S4。如果您自己将其放入字符串池中,您将再次获得与S4相同的对象,因此S5.intern() == S4将为真。

请注意,S5S4不同,不能保证。更优化的编译器可以在编译时将其放入字符串池中。

答案 6 :(得分:-1)

比较java中的字符串使用equals

在java对象中==比较内存地址

字符串S5 = S1 + S2;

S1 + S2返回新的字符串对象

某些对象具有明显的记忆地址 你可以比较使用等于

的System.out.println(S5.equals(S4));

如果连接许多字符串对象,请使用StringBuilder 他们禁食并使用最少的记忆