请您帮助我理解如果在字符串连接中使用最终变量会发生什么? 这是一个认证问题,所以不是关于如何比较字符串
的问题String var1 = "varan";
String an = "an";
final String an2 = "an";
System.out.println(var1 == ("var"+an));
System.out.println(var1 == ("var"+an2));
输出:
false
true
答案 0 :(得分:2)
TL; DR
因为"var"+an
是在运行时期间新创建的String
Object
,而"var"+an2
是编译时间常量,并且是参考var1
引用的地址相同。
请考虑以下与您的代码类似的示例。
public class TestString {
public static void main(String[] args) {
String stackOverflow = "stackOverflow";
String overflow = "Overflow";
final String overflowFinal = "Overflow";
if (overflow == overflowFinal) {
System.out.println("Both overflows are same!");
}
if (stackOverflow == ("stack" + overflow)) {
System.out.println("Stack and overflow have same reference !");
}
if (stackOverflow == ("stack" + overflowFinal)) {
System.out.println("Stack and overflowFinal have same reference !");
}
}
}
它将提供以下输出:
Both overflows are same!
Stack and overflowFinal have same reference !
首先请注意==
比较Strings
的引用而不是实际值。
JLS 15.18.1表示,
字符串连接的结果是对String对象的引用,该对象是两个操作数字符串的串联。左侧操作数的字符位于新创建的字符串中右侧操作数的字符之前。
String 对象是新创建的(§12.5),除非表达式是常量表达式(§15.28)。
因此,从上述语句中我们可以说"stack" + overflow
与String newString = new String("stackOverflow");
类似(内部编译器将使用StringBuilder
来执行此连接)。
对于final
String
JLS 4.12.4个州,
基本类型或类型
String
的变量,即final
,并使用编译时常量表达式初始化 (§15.28) ,被称为常数变量。所以 §15.28说
常量表达式是表示基本类型的值的表达式或不突然完成的
String
的表达式,仅使用以下内容组成:...
- 添加剂运算符
+
和-
...
类型为
String
的编译时常量表达式始终为“实习”,以便使用String.intern
方法共享唯一实例。
现在,上面的陈述说如果我们将String
声明为final
,它最终会成为常量表达式。
请注意String
文字也是实习。
实习String
表示您创建的String
和String
具有相同的内容(通过 .equals()
方法检查)已经存在于内存中,然后它不会创建新的String
,但会引用相同的内存位置。
例如,
String a = "test";//String literals
String b = "test";
System.out.println("Is a & b interned ? :"+(a == b));
输出
Is a & b interned ? : true