java字符串连接和实习

时间:2017-07-18 11:27:10

标签: java string-concatenation string-interning

问题1

String a1 = "I Love" + " Java";
String a2 = "I Love " + "Java";
System.out.println( a1 == a2 ); // true

String b1 = "I Love";
b1 += " Java";
String b2 = "I Love ";
b2 += "Java";
System.out.println( b1 == b2 ); // false

在第一种情况下,我理解它是两个字符串文字的串联,所以结果"我喜欢Java"将被实习,结果如实。但是,我不确定第二种情况。

问题2

String a1 = "I Love" + " Java"; // line 1
String a2 = "I Love " + "Java"; // line 2

String b1 = "I Love";
b1 += " Java";
String b2 = "I Love ";
b2 += "Java";
String b3 = b1.intern();
System.out.println( b1 == b3 ); // false

以上返回false,但如果我注释掉第1行和第2行,则返回true。那是为什么?

3 个答案:

答案 0 :(得分:6)

问题的第一部分很简单:Java编译器将多个字符串文字的连接视为单个字符串文字,即

"I Love" + " Java"

"I Love Java"

是两个相同的字符串文字,可以正确实习。

相同的实习行为适用于字符串的+=操作,因此b1b2实际上是在运行时构建的。

第二部分比较棘手。回想一下,b1.intern()可能会返回b1或与其相等的其他String个对象。当您保留a1a2时,您会从a1的电话回复b1.intern()。当您注释掉a1a2时,不会返回现有副本,因此b1.intern()会自动返回b1

答案 1 :(得分:1)

来自实习生()docs

  

所有文字字符串和字符串值常量表达式都是实体。字符串文字在The Java™Language Specification。的第3.10.5节中定义。

来自JLS 3.10.5

  
      
  • 由常量表达式计算的字符串(第15.28节)计算在   编译时间,然后将其视为文字。      
        
    • 在运行时通过串联计算的字符串是新创建的   因此不同。
    •   
  •   

你的字符串b1实际上没有实习。因此存在差异。

答案 2 :(得分:0)

回答问题1:

您无法将两个字符串与==进行比较。 ==比较两种原始数据类型(int,long,float,double和boolean)或object references 。这意味着如果参考变量(a1,a2,b1,b2)没有相同的引用(意味着它们不指向内存中的同一个对象),则它们不相等(与{{1比较) }})。

如果要与==进行比较,表达式将为真,因为对象的数据是相同的。

在第一种情况下,Java足够聪明,可以在为它们分配一些内存(甚至在编译之前)之前连接字符串,这意味着两个字符串都存储在同一个地址中。因此,变量a1和a2引用相同的对象并且相等(b1.equals(b2))。

在第二种情况下,首先为变量分配不同的值(与第一种情况不同)。这意味着他们在内存中获得了一个单独的地址。即使您更改了值以使它们相同,地址也不会更改,并且与==的比较评估为false。这在运行时发生。

关于问题2:@dasblinkenlight已经给出了一个很好的答案。