繁体   English   中英

java字符串连接和实习

[英]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"

是两个相同的字符串文字,它们被正确地插入。

同样的实习行为并不适用于+=对字符串的操作,所以b1b2在运行时实际构成。

第二部分比较棘手。 回想一下b1.intern()可能会返回b1或其他与它相等的String对象。 当您保留a1a2 ,您会从对b1.intern()的调用中获得a1 当您注释掉a1a2 ,没有要返回的现有副本,因此b1.intern()将返回b1本身。

来自 intern() 文档

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

JLS 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM