String a = "devender";
String b = "devender";
String c = "dev";
String d = "dev" + "ender";
String e = c + "ender";
System.out.println(a == b); //case 1: o/p true
System.out.println(a == d); //case 2: o/p true
System.out.println(a == e); //case 3: o/p false
a & b两者都指向字符串常量池中的相同字符串文字。所以true
在情况1中
String d = "dev" + "ender";
应该在内部使用类似的东西:
String d = new StringBuilder().append("dev").append("ender").toString();
How a & d指向相同的引用而不是a & e ?
有四件事正在发生:
(你显然知道这一点,但对于潜伏者来说)==
测试变量是否指向same String
object, not 相等的字符串。所以即使x
is "foo"
and y
也是"foo"
, x == y
可能是真的也可能是假的,取决于是否x
and y
参考相同的String
对象或不同的对象。这就是为什么我们使用equals http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#equals-java.lang.Object-, not ==
,比较字符串是否相等。以下所有内容只是为了解释原因==
有时是正确的,这不是建议使用==
比较字符串。 :-)
同一类中的等效字符串常量(根据 JLS 中的各种规则,编译器知道是常量的字符串)由编译器引用相同的字符串(编译器还将它们列在类的“常量池” https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4)。这就是为什么a == b
是真的。
-
当类被加载时,它的每个字符串常量都会自动interned http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#intern--— 检查 JVM 的字符串池是否有等效字符串,如果找到,则表明String
使用对象(如果没有,则使用新的String
新常量的对象被添加到池中)。所以即使x
是在类中初始化的字符串常量Foo
and y
是在类中初始化的字符串常量Bar
,他们将是==
彼此。
上述第 2 点和第 3 点已部分涵盖JLS§3.10.5 https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5。 (关于类常量池的部分是一些实现细节,因此之前链接到了 JVM 规范;JLS 只是谈到了实习。)
-
如果编译器处理常量值,则会进行字符串连接,因此
String d = "dev" + "ender";
被编译为
String d = "devender";
and "devender"
是编译器和 JVM 应用上面第 2 点和第 3 点的字符串常量。例如,不StringBuilder
使用时,串联发生在编译时,而不是运行时。这涵盖在JLS§15.28 -常量表达式 https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28. So a == d
出于同样的原因也是如此a == b
为 true:它们引用相同的常量字符串,因此编译器确保它们引用类常量池中的相同字符串。
当任何操作数不是常量时,编译器无法执行此操作,因此它不能使用以下命令执行此操作:
String e = c + "ender";
...尽管代码分析可以很容易地表明c
肯定会"dev"
因此e
肯定会"devender"
。具体而言,规范仅让编译器与常量值进行串联。因此,由于编译器无法执行此操作,因此它输出StringBuilder
您提到的代码并且工作是在运行时完成的,创建一个新的String
目的。该字符串不会自动保留,所以e
最终指的是不同的String
对象比a
确实如此,所以a == e
是假的。
注意正如维诺德所说 https://stackoverflow.com/questions/34509566/in-case-of-string-concatenation-in-java/34509659#comment56760592_34509566,如果你声明c
as final
:
final String c = "dev";
那么这将是一个常数变量 https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4(是的,它们确实是这样称呼的),因此 §15.28 将适用,编译器将变成
String e = c + "ender";
into
String e = "devender";
and a == e
也将是真的。
只是重申一下:这并不意味着我们应该使用==
比较字符串是否相等。 :-) 就是这样equals
is for.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)