简体   繁体   English

JShell / Java 9中的相等性是怎么回事?

[英]What is going on with equality in JShell/Java 9?

I've been using JShell a bit just to test it out, and today I came across quite the interesting bit of behavior. 我一直在使用JShell来测试它,今天我遇到了相当有趣的行为。

jshell> String a = "A"
a ==> "A"

jshell> String b = "A"
b ==> "A"

jshell> a == b
$4 ==> true

jshell> "A" == "A"
$5 ==> true

I was first wondering if this was a feature of Java 9, and I checked it out by compiling and running this program with Java 9 我首先想知道这是否是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");
    }
}

And interestingly enough I got 有趣的是,我得到了

 a == b true "A" == "A" true 

As my output as well. 作为我的输出也是如此。 What's going on here? 这里发生了什么? Why are a and b equal to each other and why is "A" == "A" true? 为什么ab彼此相等,为什么"A" == "A"真的?

Why shouldn't it be? 为什么不应该呢? This behaviour is exhibited in previous Java versions as well - String literals are interned. 此行为也在以前的Java版本中展示 - 字符串文字被实现。

As you know, == checks for reference equality - the two variables have the same memory address. 如您所知, ==检查引用相等性 - 两个变量具有相同的内存地址。 When a String is interned, all references of that string point to the intern pool and thus will be equal using == . 当一个String被实现时,该字符串的所有引用都指向实习池,因此使用==将是相等的。

I just wanted to add this demonstration alongside Sinkingpoint's fine answer. 我只是想把这个演示与Sinkingpoint的精彩答案一起添加。
It's not safe to use == on Strings unless you know the origin of each, since a String that is built-up in some way (such as the new String("A") in Eli's comment or the .toString() used here) is not the same reference even if the two do use the same underlying character array. 在字符串上使用==是不安全的,除非你知道每个字符串的来源,因为以某种方式构建的字符串(例如Eli评论中的new String("A")或此处使用的.toString() )即使两者使用相同的底层字符数组,也不是相同的引用

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));
  }
}

The output from this (run on https://repl.it/languages/java ) is: 此输出(在https://repl.it/languages/java上运行)是:

A == A -> true
oneA == twoA -> true
oneA == three -> false
oneA.intern() == three.intern() -> true
oneA .equals three -> true

You can safely use string1.equals(string2) or string1.intern() == string2.intern() 您可以安全地使用string1.equals(string2)string1.intern() == string2.intern()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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