[英]java string concatenation and 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
在第一种情况下,我知道它是两个字符串文字的串联,因此结果“I Love 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。 这是为什么?
您问题的第一部分很简单:Java 编译器将多个字符串文字的串联视为单个字符串文字,即
"I Love" + " Java"
和
"I Love Java"
是两个相同的字符串文字,它们被正确地插入。
同样的实习行为并不适用于+=
对字符串的操作,所以b1
和b2
在运行时实际构成。
第二部分比较棘手。 回想一下b1.intern()
可能会返回b1
或其他与它相等的String
对象。 当您保留a1
和a2
,您会从对b1.intern()
的调用中获得a1
。 当您注释掉a1
和a2
,没有要返回的现有副本,因此b1.intern()
将返回b1
本身。
来自 intern() 文档
所有文字字符串和字符串值常量表达式都被实习。 字符串文字在 Java™ 语言规范的第 3.10.5 节中定义。
- 由常量表达式(第 15.28 节)计算的字符串在编译时计算,然后将它们视为文字。
- 在运行时通过连接计算的字符串是新创建的,因此是不同的。
你的字符串 b1 实际上没有被实习。 因此差异。
问题1的答案:
您不能将两个String与==
进行比较。 ==
比较两种原始数据类型(int,long,float,double和boolean)或对象引用 。 这意味着如果引用变量(a1,a2,b1,b2)没有相同的引用(意味着它们不指向内存中的同一个对象),则它们不相等(与==
比较)。
如果要与b1.equals(b2)
进行比较,则表达式将为true,因为对象的数据是相同的。
在第一种情况下,Java足够聪明,可以在为它们分配一些内存(甚至在编译之前)之前连接字符串,这意味着两个字符串都存储在同一个地址中。 因此,变量a1和a2引用相同的对象并且相等( ==
)。
在第二种情况下,首先为变量分配不同的值(与第一种情况不同)。 这意味着他们在内存中获得了一个单独的地址。 即使您更改了值以使它们相同,地址也不会更改,并且与==
的比较计算结果为false。 这在运行时发生。
至于问题2:@dasblinkenlight已经给出了一个很好的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.