Java中==和equals()之间有什么区别?

bra*_*ter 592 java identity equality object-comparison

我想澄清一下我是否理解正确:

  • == - >是参考比较,即两个对象都指向相同的内存位置
  • .equals() - >计算对象中值的比较

我的理解是正确的吗?

Hov*_*els 604

一般来说,你的问题的答案是"是",但......

  • .equals(...) 只会比较它所写的比较,不多也不少.
  • 如果一个类没有覆盖equals方法,那么它默认为equals(Object o)覆盖此方法的最近父类的方法.
  • 如果没有父类提供覆盖,那么它默认为最终父类Object的方法,因此您将使用该Object#equals(Object o)方法.根据Object API,它与==; 也就是说,当且仅当两个变量引用同一个对象时,如果它们的引用是同一个,它才返回true .因此,您将测试对象相等性而不是功能相等性.
  • hashCode如果你改写equals,总是记得覆盖,以免"违反合同".根据API,如果hashCode()两个对象的方法表明它们是等价的,那么从两个对象的方法返回的结果必须相同equals.反过来并不一定是真的.

  • @JSK打印d1和d2的值,我想你会明白为什么你会返回false. (4认同)
  • @BoDidely我明白了.这是因为所有包装类都是不可变的. (2认同)

小智 104

关于String类:

equals()方法比较String实例(在堆上)中的"值",而不管两个对象引用是否引用相同的String实例.如果任何两个String类型的对象引用引用相同的String实例那么太棒了!如果两个对象引用引用两个不同的String实例,则它没有区别.它是正在比较的每个String实例中的"值"(即:字符数组的内容).

另一方面,"==" 运算符比较两个对象引用的值,以查看它们是否引用相同的String实例.如果两个对象引用的值"引用"相同的String实例,则布尔表达式的结果将为"true".. duh.另一方面,如果两个对象引用的值"引用" 不同的String实例(即使两个String实例具有相同的"值",也就是说,每个String实例的字符数组的内容都相同)布尔表达式的结果将为"false".

与任何解释一样,让它沉入其中.

我希望这可以解决一些问题.

  • 添加Tonio的评论.字符串文字的`String`构建将被添加到称为`String constant pool`的东西中,例如`String s1 ="someString"; String s2 ="someString;"``s1`和`s2`将共享相同的引用.`s1 == s2`将返回true.但是如果它们是通过`String构造函数`构造的,例如`String s1 = new String("someString"); String s2 = new String("someString");`那么它们不会共享相同的引用.`s1 == s2`将返回false. (5认同)
  • (螺纹巫术,我知道...)对于`String`s,``==参考是等于为好,是的,但它_usually_工作(如具有相同内容的两个`String`s将_usually_是`== "彼此",因为Java如何处理`String`s.它并不总是,这当然是不好的做法,但这是一个常见的错误,特别是来自其他语言的人. (2认同)

Alm*_*pos 58

根据您是在谈论"原语"还是"对象类型",存在一些小差异; 如果你在谈论"静态"或"非静态"成员,也可以这样说; 你也可以混合以上所有......

这是一个例子(你可以运行它):

public final class MyEqualityTest
{
    public static void main( String args[] )
    {
        String s1 = new String( "Test" );
        String s2 = new String( "Test" );

        System.out.println( "\n1 - PRIMITIVES ");
        System.out.println( s1 == s2 ); // false
        System.out.println( s1.equals( s2 )); // true

        A a1 = new A();
        A a2 = new A();

        System.out.println( "\n2 - OBJECT TYPES / STATIC VARIABLE" );
        System.out.println( a1 == a2 ); // false
        System.out.println( a1.s == a2.s ); // true
        System.out.println( a1.s.equals( a2.s ) ); // true

        B b1 = new B();
        B b2 = new B();

        System.out.println( "\n3 - OBJECT TYPES / NON-STATIC VARIABLE" );
        System.out.println( b1 == b2 ); // false
        System.out.println( b1.getS() == b2.getS() ); // false
        System.out.println( b1.getS().equals( b2.getS() ) ); // true
    }
}

final class A
{
    // static
    public static String s;
    A()
    {
        this.s = new String( "aTest" );
    }
}

final class B
{
    private String s;
    B()
    {
        this.s = new String( "aTest" );
    }

    public String getS()
    {
        return s;
    }

}
Run Code Online (Sandbox Code Playgroud)

您可以通过以下链接比较"=="(Equality Operator)和".equals(...)"(java.lang.Object类中的方法)的解释:

  • 有趣的例子.从上面的答案不同的角度来看.谢谢! (2认同)

gov*_*tel 44

==和equals之间的区别让我困惑了一段时间,直到我决定仔细看看它.他们中的许多人说比较字符串你应该使用equals和不使用==.希望在这个答案中我能够说出不同之处.

回答这个问题的最好方法是向自己提出几个问题.让我们开始吧:

以下程序的输出是什么:

String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);
Run Code Online (Sandbox Code Playgroud)

如果你说,

false
true
Run Code Online (Sandbox Code Playgroud)

我会说你是对的,你为什么这么说呢?如果你说输出是,

true
false
Run Code Online (Sandbox Code Playgroud)

我会说你错了,但我仍会问你,为什么你认为这是对的?

好的,让我们试着回答这个:

以下程序的输出是什么:

String mango = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);
Run Code Online (Sandbox Code Playgroud)

现在如果你说,

false
true
Run Code Online (Sandbox Code Playgroud)

我会说你错了,为什么现在错了?该程序的正确输出是

true
false
Run Code Online (Sandbox Code Playgroud)

请比较上面的程序,并尝试考虑它.

好.现在这可能有所帮助(请阅读:打印对象的地址 - 不可能,但我们仍然可以使用它.)

String mango = "mango";
String mango2 = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(mango3 != mango2);
System.out.println(mango3 == mango2);
// mango2 = "mang";
System.out.println(mango+" "+ mango2);
System.out.println(mango != mango2);
System.out.println(mango == mango2);

System.out.println(System.identityHashCode(mango));
System.out.println(System.identityHashCode(mango2));
System.out.println(System.identityHashCode(mango3));
Run Code Online (Sandbox Code Playgroud)

你可以尝试考虑上面代码中最后三行的输出:对我来说,意思是打印出来的(你可以在这里查看代码):

false
true
true
false
mango mango
false
true
17225372
17225372
5433634
Run Code Online (Sandbox Code Playgroud)

哦! 现在你看到identityHashCode(mango)等于identityHashCode(mango2)但是它不等于identityHashCode(mango3)

尽管所有字符串变量 - 芒果,芒果2和芒果3 - 具有相同的值,即"芒果",identityHashCode()但对所有人来说仍然不一样.

现在尝试取消注释这一行// mango2 = "mang";并再次运行它,这次你将看到所有三个identityHashCode()都不同.嗯这是一个有用的提示

我们知道if hashcode(x)=Nhashcode(y)=N=>x is equal to y

我不确定java内部是如何工作的,但我认为这就是我说的时候发生的事情:

mango = "mango";
Run Code Online (Sandbox Code Playgroud)

Java的创建一个字符串,"mango"它指出(参考)由变量mango是这样的

mango ----> "mango"
Run Code Online (Sandbox Code Playgroud)

现在在下一行我说:

mango2 = "mango";
Run Code Online (Sandbox Code Playgroud)

它实际上重用了"mango"看起来像这样的字符串

mango ----> "mango" <---- mango2
Run Code Online (Sandbox Code Playgroud)

芒果和芒果2指向相同的参考现在,当我说

mango3 = new String("mango")
Run Code Online (Sandbox Code Playgroud)

它实际上为"芒果"创建了一个全新的引用(字符串).看起来像这样,

mango -----> "mango" <------ mango2

mango3 ------> "mango"
Run Code Online (Sandbox Code Playgroud)

这就是为什么当我推出它的价值时mango == mango2,它就推出了true.当我拿出它的值时mango3 == mango2,它就会被推出false(即使值相同).

当你取消注释该行// mango2 = "mang"; 它实际上创建了一个字符串"mang",它将我们的图形转换为:

mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"
Run Code Online (Sandbox Code Playgroud)

这就是为什么identityHashCode对所有人都不一样.

希望这可以帮助你们.实际上,我想生成一个测试用例,其中==失败并且equals()通过.如果我错了,请随时发表评论并告诉我.


dhe*_*ran 29

==操作符测试两个变量是否有相同的引用(又名指向一个内存地址).

String foo = new String("abc");
String bar = new String("abc");

if(foo==bar)
// False (The objects are not the same)

bar = foo;

if(foo==bar)
// True (Now the objects are the same)
Run Code Online (Sandbox Code Playgroud)

equals()方法测试两个变量是否引用具有相同状态(值)的对象.

String foo = new String("abc");
String bar = new String("abc");

if(foo.equals(bar))
// True (The objects are identical but not same)
Run Code Online (Sandbox Code Playgroud)

干杯:-)

  • @JohnathanLogan我猜它是由于字符串实习.现在我已经改为"new String("abc")".希望现在不会有任何问题.谢谢你的通知. (2认同)

And*_*arr 12

您必须覆盖equals函数(以及其他函数)才能将其与自定义类一起使用.

equals方法比较对象.

==二进制运算符比较的内存地址.


tin*_*tin 7

如果不覆盖.equals(),==和.equals()都指向同一个对象.

一旦你覆盖.equals(),你希望你想做什么.您可以将调用对象的状态与传入的对象的状态进行比较,也可以调用super.equals()


Cha*_*oka 7

==运算符:

==是Java中的关系运算符,用于比较两个操作数。它用于确定两个操作数是否相等。使用==运算符,可以比较任何原始类型,例如int,char,float和Boolean。比较之后,==运算符返回一个布尔值。如果两个操作数相等,则==运算符将返回一个真值。但是,如果两个操作数不相等,则返回错误值。当与对象一起使用时,==运算符将比较两个对象引用,并确定它们是否引用同一实例。

.equals()方法

equals()是String类中可用的方法,用于比较两个字符串并确定它们是否相等。作为比较的结果,此方法返回布尔值。如果两个字符串包含相同顺序的相同字符,则equals()方法返回true。否则,它返回一个假值。


ayn*_*iam 6

==是一个运算符,equals()是一种方法.

运算符通常用于原始类型比较,因此==用于存储器地址比较,并且equals()方法用于比较对象.


Tad*_*egn 6

relational operator ==以下是区分和之间的一般规则the method .equals()

object1 == object2比较 object1 和 object2 引用的对象是否引用Heap 中的同一内存位置

object1.equals(object2)比较object1 和 object2 的值,无论它们位于内存中的哪个位置

使用 String 可以很好地证明这一点

场景1

 public class Conditionals {

    public static void main(String[] args) {
       String str1 = "Hello";
       String str2 = new String("Hello");
       System.out.println("is str1 == str2 ? " + (str1 == str2 ));
       System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
    }

 }



The result is
      is str1 == str2 ? false
      is str1.equals(str2) ? true 
Run Code Online (Sandbox Code Playgroud)

场景2

public class Conditionals {

    public static void main(String[] args) {
       String str1 = "Hello";
       String str2 = "Hello";
       System.out.println("is str1 == str2 ? " + (str1 == str2 ));
       System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
    }

}

The result is 
  is str1 == str2 ? true
  is str1.equals(str2) ? true
Run Code Online (Sandbox Code Playgroud)

该字符串比较可以用作比较其他类型对象的基础。

例如,如果我有一个 Person 类,我需要定义比较两个人的标准。假设这个 person 类有身高和体重的实例变量。

因此,创建 person 对象person1 and person2并使用这两个对象进行比较,.equals()我需要重写person 类的 equals 方法来定义基于哪些实例变量(身高或体重)进行比较。

但是,那== operator will still return results based on the memory location of the two objects(person1 and person2)

为了便于概括此人对象比较,我创建了以下测试类。对这些概念进行实验将揭示大量事实

package com.tadtab.CS5044;

public class Person {

private double height;
private double weight;

public double getHeight() {
    return height;
}

public void setHeight(double height) {
    this.height = height;
}

public double getWeight() {
    return weight;
}

public void setWeight(double weight) {
    this.weight = weight;
}


@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    long temp;
    temp = Double.doubleToLongBits(height);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    return result;
}

@Override
/**
 * This method uses the height as a means of comparing person objects.
 * NOTE: weight is not part of the comparison criteria
 */
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Person other = (Person) obj;
    if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
        return false;
    return true;
}

public static void main(String[] args) {
    
    Person person1 = new Person();
    person1.setHeight(5.50);
    person1.setWeight(140.00);
    
    Person person2 = new Person();
    person2.setHeight(5.70);
    person2.setWeight(160.00);
    
    Person person3 = new Person();
    person3 = person2;
    
    Person person4 = new Person();
    person4.setHeight(5.70);
    
    Person person5 = new Person();
    person5.setWeight(160.00);
    
    System.out.println("is person1 == person2 ? " + (person1 == person2)); // false;
    System.out.println("is person2 == person3 ? " + (person2 == person3)); // true 
    //this is because perosn3 and person to refer to the one person object in memory. They are aliases;
    System.out.println("is person2.equals(person3) ? " + (person2.equals(person3))); // true;
    
    System.out.println("is person2.equals(person4) ? " + (person2.equals(person4))); // true;
    
    // even if the person2 and person5 have the same weight, they are not equal.
    // it is because their height is different
    System.out.println("is person2.equals(person4) ? " + (person2.equals(person5))); // false;
}

}
Run Code Online (Sandbox Code Playgroud)

该类的执行结果为:

is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false
Run Code Online (Sandbox Code Playgroud)


fru*_*ose 5

请记住,.equals(...)必须由您要比较的类实现.否则,没有太大意义; Object类的方法版本与比较操作的作用相同:Object#equals.

您真正想要使用对象的比较运算符的唯一时间是您要比较枚举.这是因为一次只有一个枚举值的实例.例如,鉴于枚举

enum FooEnum {A, B, C}
Run Code Online (Sandbox Code Playgroud)

你永远不会有多个实例A,而且BC.这意味着您实际上可以编写如下方法:

public boolean compareFoos(FooEnum x, FooEnum y)
{
    return (x == y);
}
Run Code Online (Sandbox Code Playgroud)

而且你没有任何问题.


Sar*_*dra 5

 String w1 ="Sarat";
 String w2 ="Sarat";
 String w3 = new String("Sarat");

 System.out.println(w1.hashCode());   //3254818
 System.out.println(w2.hashCode());   //3254818
 System.out.println(w3.hashCode());   //3254818

 System.out.println(System.identityHashCode(w1)); //prints 705927765
 System.out.println(System.identityHashCode(w2)); //prints 705927765
 System.out.println(System.identityHashCode(w3)); //prints 366712642


 if(w1==w2)   //  (705927765==705927765)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints true

 if(w2==w3)   //  (705927765==366712642)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints false


 if(w2.equals(w3))   //  (Content of 705927765== Content of 366712642)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints true
Run Code Online (Sandbox Code Playgroud)