JShell/Java 9 中的平等是怎么回事?
What is going on with equality in JShell/Java 9?
我一直在使用 JShell 来测试它,今天我遇到了一些非常有趣的行为。
jshell> String a = "A"
a ==> "A"
jshell> String b = "A"
b ==> "A"
jshell> a == b
==> true
jshell> "A" == "A"
==> true
我首先想知道这是否是 Java 9 的一个特性,我通过使用 Java 9
编译和 运行 这个程序来检查它
public class Equus {
public static void main(String... args) {
String a = "A";
String b = "A";
System.out.println("a == b");
System.out.println(a == b);
System.out.println("\"A\" == \"A\"");
System.out.println("A" == "A");
}
}
有趣的是我得到了
a == b
true
"A" == "A"
true
作为我的输出也是如此。这里发生了什么?为什么 a
和 b
彼此相等,为什么 "A" == "A"
为真?
为什么不应该呢?此行为也出现在以前的 Java 版本中 - 字符串文字被保留。
如您所知,==
检查引用是否相等 - 两个变量具有相同的内存地址。当一个 String 被 intern 时,该字符串的所有引用都指向 intern 池,因此使用 ==
将是相等的。
我只是想在 Sinkingpoint 的精彩回答旁边添加这个演示。
在字符串上使用 ==
是不安全的,除非您知道每个字符串的来源,因为字符串在某种程度上是 built-up(例如 Eli 评论中的 new String("A")
或 .toString()
在这里使用)是不一样的 reference 即使两者确实使用相同的底层字符数组。
class Main
{
public static void main(String[] args)
{
String oneA = "A";
String twoA = "A";
String three = new StringBuilder().append('A').toString();
// We expect constant literals to be ==
System.out.print("A == A -> ");
System.out.println("A" == "A");
// Variables assigned the same literal are also ==
System.out.print("oneA == twoA -> ");
System.out.println(oneA == twoA);
// but a built-up String var is not == to the "literal" var.
System.out.print("oneA == three -> ");
System.out.println(oneA == three);
// If we intern() them they are again ==
System.out.print("oneA.intern() == three.intern() -> ");
System.out.println(oneA.intern() == three.intern());
// and of course, .equals() is always safe.
System.out.print("oneA .equals three -> ");
System.out.println(oneA.equals(three));
}
}
此(运行 在 https://repl.it/languages/java 上)的输出是:
A == A -> true
oneA == twoA -> true
oneA == three -> false
oneA.intern() == three.intern() -> true
oneA .equals three -> true
您可以安全地使用 string1.equals(string2)
或 string1.intern() == string2.intern()
我一直在使用 JShell 来测试它,今天我遇到了一些非常有趣的行为。
jshell> String a = "A"
a ==> "A"
jshell> String b = "A"
b ==> "A"
jshell> a == b
==> true
jshell> "A" == "A"
==> true
我首先想知道这是否是 Java 9 的一个特性,我通过使用 Java 9
编译和 运行 这个程序来检查它public class Equus {
public static void main(String... args) {
String a = "A";
String b = "A";
System.out.println("a == b");
System.out.println(a == b);
System.out.println("\"A\" == \"A\"");
System.out.println("A" == "A");
}
}
有趣的是我得到了
a == b true "A" == "A" true
作为我的输出也是如此。这里发生了什么?为什么 a
和 b
彼此相等,为什么 "A" == "A"
为真?
为什么不应该呢?此行为也出现在以前的 Java 版本中 - 字符串文字被保留。
如您所知,==
检查引用是否相等 - 两个变量具有相同的内存地址。当一个 String 被 intern 时,该字符串的所有引用都指向 intern 池,因此使用 ==
将是相等的。
我只是想在 Sinkingpoint 的精彩回答旁边添加这个演示。
在字符串上使用 ==
是不安全的,除非您知道每个字符串的来源,因为字符串在某种程度上是 built-up(例如 Eli 评论中的 new String("A")
或 .toString()
在这里使用)是不一样的 reference 即使两者确实使用相同的底层字符数组。
class Main
{
public static void main(String[] args)
{
String oneA = "A";
String twoA = "A";
String three = new StringBuilder().append('A').toString();
// We expect constant literals to be ==
System.out.print("A == A -> ");
System.out.println("A" == "A");
// Variables assigned the same literal are also ==
System.out.print("oneA == twoA -> ");
System.out.println(oneA == twoA);
// but a built-up String var is not == to the "literal" var.
System.out.print("oneA == three -> ");
System.out.println(oneA == three);
// If we intern() them they are again ==
System.out.print("oneA.intern() == three.intern() -> ");
System.out.println(oneA.intern() == three.intern());
// and of course, .equals() is always safe.
System.out.print("oneA .equals three -> ");
System.out.println(oneA.equals(three));
}
}
此(运行 在 https://repl.it/languages/java 上)的输出是:
A == A -> true
oneA == twoA -> true
oneA == three -> false
oneA.intern() == three.intern() -> true
oneA .equals three -> true
您可以安全地使用 string1.equals(string2)
或 string1.intern() == string2.intern()