关于identity:Java中的==和equals()的区别是什么?

What is the difference between == and equals() in Java?

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

  • ==->是一个引用比较,即两个对象都指向相同的内存位置
  • .equals()->对对象中的值进行比较

我的理解正确吗?


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

  • .equals(...)只会比较它所写的内容,不多也不少。
  • 如果一个类不重写equals方法,那么它默认为已重写此方法的最近父类的equals(Object o)方法。
  • 如果没有父类提供覆盖,那么它默认为来自最终父类、对象的方法,因此您只剩下Object#equals(Object o)方法。对于对象API,这与==相同;也就是说,只有当两个变量引用同一个对象(如果它们的引用是一个且相同)时,才会返回true。因此,您将测试对象相等性而不是函数相等性。
  • 如果您覆盖equals,请务必记住覆盖hashCode,以免"违反合同"。根据API,如果两个对象的equals方法表明它们是等效的,则从hashCode()方法返回的结果必须相同。反过来说不一定是真的。


关于字符串类:

equals()方法比较字符串实例(堆上)中的"value",而不管两个对象引用是否引用同一个字符串实例。如果任何两个字符串类型的对象引用引用同一个字符串实例,那么太好了!如果这两个对象引用引用了两个不同的字符串实例。这没什么区别。它是要比较的每个字符串实例中的"值"(即:字符数组的内容)。

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

就像任何解释一样,让它沉入其中。

我希望这能让事情有所改观。


根据您所说的是"原语"还是"对象类型",有一些细微的区别;如果您所说的是"静态"或"非静态"成员,也可以这样说;您还可以混合以上所有内容…

下面是一个示例(您可以运行它):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public final class MyEqualityTest
{
    public static void main( String args[] )
    {
        String s1 = new String("Test" );
        String s2 = new String("Test" );

        System.out.println("
1 - 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("
2 - 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("
3 - 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;
    }

}

您可以通过以下链接比较"=="(相等运算符)和".equals(…)"(java.lang.object类中的方法)的解释:

  • ==:http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
  • 等号(…):http://DOCS.Oracle .COM/JavaSe/ 7 /DOCS/API/Java/Lang/Objult.HTML.YAL(Java.Lang.Object)


有段时间,==和等于之间的差异让我困惑,直到我决定仔细观察它。他们中的许多人说,为了比较字符串,应该使用equals,而不是==。希望在这个答案中我能说出不同之处。

回答这个问题的最好方法就是问自己几个问题。那么,让我们开始:

以下程序的输出是什么:

1
2
3
4
String mango ="mango";
String mango2 ="mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);

如果你说,

1
2
false
true

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

1
2
true
false

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

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

以下程序的输出是什么:

1
2
3
4
String mango ="mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);

如果你说,

1
2
false
true

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

1
2
true
false

请比较一下上面的程序并试着思考一下。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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));

你能试着想想上面代码中最后三行的输出吗?对于我来说,Ideone打印了这个(你可以在这里检查代码):

1
2
3
4
5
6
7
8
9
10
false
true
true
false
mango mango
false
true
17225372
17225372
5433634

哦!现在您看到IdentityHashCode(mango)等于IdentityHashCode(mango2),但它不等于IdentityHashCode(mango3)

尽管所有字符串变量(mango、mango 2和mango 3)的值都相同,即"mango",但identityHashCode()对所有变量来说仍然不相同。

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

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

我不确定Java是如何内部工作的,但我认为这是我说的:

1
mango ="mango";

Java创建了一个字符串EDCOX1,12,它是由变量EDCOX1,13(例如)指向的(引用)。

1
mango ---->"mango"

接下来我说:

1
mango2 ="mango";

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

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

芒果和芒果2都指向同一参考现在当我说

1
mango3 = new String("mango")

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

1
2
3
mango ----->"mango" <------ mango2

mango3 ------>"mango"

这就是为什么当我给出mango == mango2的值时,它给出了true。当我计算出EDOCX1的值(17)时,它计算出EDOCX1的值(18)(即使这些值相同)。

当您取消对行EDOCX1的注释时它实际上创建了一个字符串"mang",它将我们的图形转换为如下:

1
2
3
mango ---->"mango"
mango2 ---->"mang"
mango3 ----->"mango"

这就是为什么IdentityHashCode对所有人都不相同的原因。

希望这对你们有帮助。实际上,我想生成一个测试用例,其中==失败,等于()通过。请随时发表评论,如果我错了请告诉我。


The == operator tests whether two variables have the same references
(aka pointer to a memory address).

1
2
3
4
5
6
7
8
9
10
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)

Whereas the equals() method tests whether two variables refer to objects
that have the same state (values).

1
2
3
4
5
String foo = new String("abc");
String bar = new String("abc");

if(foo.equals(bar))
// True (The objects are identical but not same)

干杯:


您必须重写equals函数(连同其他函数)才能将其与自定义类一起使用。

equals方法比较对象。

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


如果不重写.equals(),则==和.equals()都引用同一对象。

重写.equals()后,您希望做什么。可以将调用对象的状态与传入对象的状态进行比较,也可以只调用super.equals()。


==运算符:

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

.equals()方法

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 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


请记住,.equals(...)必须由您要比较的类实现。否则,没有太多的点;对象类的方法版本与比较操作执行相同的操作:object equals。

唯一一次真正想对对象使用比较运算符的是Wen You正在比较枚举。这是因为一次只有一个枚举值的实例。例如,给定枚举

1
enum FooEnum {A, B, C}

一次最多只能有一个A实例,对于BC实例也是如此。这意味着您实际上可以编写这样的方法:

1
2
3
4
public boolean compareFoos(FooEnum x, FooEnum y)
{
    return (x == y);
}

你不会有任何问题的。


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

运算符通常用于原始类型比较,因此==用于内存地址比较,equals()方法用于对象比较。


还要注意,.equals()通常包含用于测试的==,因为如果您想测试两个对象是否相等,这是您希望测试的第一件事情。

==实际上是在查看原始类型的值,对于它检查引用的对象。


当您评估代码时,很明显(=)会根据内存地址进行比较,而equals(object o)会比较实例的hashcode()。这就是为什么人们说,如果以后不遇到意外,就不要破坏equals()和hashcode()之间的契约。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    String s1 = new String("Ali");
    String s2 = new String("Veli");
    String s3 = new String("Ali");

    System.out.println(s1.hashCode());
    System.out.println(s2.hashCode());
    System.out.println(s3.hashCode());


    System.out.println("(s1==s2):" + (s1 == s2));
    System.out.println("(s1==s3):" + (s1 == s3));


    System.out.println("s1.equals(s2):" + (s1.equals(s2)));
    System.out.println("s1.equal(s3):" + (s1.equals(s3)));


    /*Output
    96670    
    3615852
    96670
    (s1==s2):false
    (s1==s3):false
    s1.equals(s2):false
    s1.equal(s3):true
    */

==和equals()之间的主要区别是

1)==用于比较原语。

例如:

1
2
3
4
5
6
7
        String string1 ="Ravi";
        String string2 ="Ravi";
        String string3 = new String("Ravi");
        String string4 = new String("Prakash");

        System.out.println(string1 == string2); // true because same reference in string pool
        System.out.println(string1 == string3); // false

2)equals()用于比较对象。例如:

1
2
3
        System.out.println(string1.equals(string2)); // true equals() comparison of values in the objects
        System.out.println(string1.equals(string3)); // true
        System.out.println(string1.equals(string4)); // false


==可用于许多对象类型,但您可以将Object.equals用于任何类型,尤其是字符串和谷歌地图标记。


如果两个值相等,那么对于基本类型(即int、long、double-==的包装器对象)来说,可能值得添加一点。

1
2
3
4
5
6
Long a = 10L;
Long b = 10L;

if (a == b) {
    System.out.println("Wrapped primitives behave like values");
}

相比之下,将上面的两个long放入两个单独的arraylist中,equals将它们视为相同的,但==不一样。

1
2
3
4
5
6
7
ArrayList<Long> c = new ArrayList<>();
ArrayList<Long> d = new ArrayList<>();

c.add(a);
d.add(b);
if (c == d) System.out.println("No way!");
if (c.equals(d)) System.out.println("Yes, this is true.");

==比较运算符始终引用。但万一

equals() method

它依赖于实现,如果我们被重写,它就等于方法,而不是在重写方法中给出的实现的基础上比较对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 class A
 {
   int id;
   String str;

     public A(int id,String str)
     {
       this.id=id;
       this.str=str;
     }

    public static void main(String arg[])
    {
      A obj=new A(101,"sam");
      A obj1=new A(101,"sam");

      obj.equals(obj1)//fasle
      obj==obj1 // fasle
    }
 }

在上面的代码中,obj和obj1对象都包含相同的数据,但引用不相同,因此等于返回false和==also。但如果我们重写equals方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 class A
 {
   int id;
   String str;

     public A(int id,String str)
     {
       this.id=id;
       this.str=str;
     }
    public boolean equals(Object obj)
    {
       A a1=(A)obj;
      return this.id==a1.id;
    }

    public static void main(String arg[])
    {
      A obj=new A(101,"sam");
      A obj1=new A(101,"sam");

      obj.equals(obj1)//true
      obj==obj1 // fasle
    }
 }

知道吗,签出它将返回正确和错误的同一个案件,只有我们重写

equals method .

它基于对象的内容(ID)比较对象

but ==

仍然比较对象的引用。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class StringPool {

public static void main(String[] args) {

    String s1 ="Cat";// will create reference in string pool of heap memory
    String s2 ="Cat";
    String s3 = new String("Cat");//will create a object in heap memory

    // Using == will give us true because same reference in string pool

    if (s1 == s2) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    // Using == with reference and Object will give us False

    if (s1 == s3) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    // Using .equals method which refers to value

    if (s1.equals(s3)) {
        System.out.println("true");
    } else {
        System.out.println("False");
    }

    }
  }

----输出——真假真


简而言之,答案是"是"。

在Java中,EDCOX1×0×操作符比较两个对象,以查看它们是否指向相同的内存位置;而EDCOX1×12的方法实际上比较了两个对象,以查看它们是否具有相同的对象值。


字符串池(又称中间池)和整数池进一步模糊了差异,并且在某些情况下允许您对对象使用==,而不是.equals

这可以给你更好的表现(?)以更大的复杂性为代价。

例如。:

1
2
3
4
5
assert"ab" =="a" +"b";

Integer i = 1;
Integer j = i;
assert i == j;

复杂性权衡:以下可能会让您感到惊讶:

1
2
3
4
5
assert new String("a") != new String("a");

Integer i = 128;
Integer j = 128;
assert i != j;

我建议您远离这种微观优化,始终使用.equals表示对象,使用==表示原语:

1
2
3
4
5
assert (new String("a")).equals(new String("a"));

Integer i = 128;
Integer j = 128;
assert i.equals(j);

基本上,==比较两个对象在堆上具有相同的引用,因此除非两个引用链接到同一个对象,否则此比较将为假。

equals()是从Object类继承的方法。默认情况下,此方法比较两个对象是否具有相同的引用。它的意思是:

object1.equals(object2)<=>object1 == object2

但是,如果要在同一类的两个对象之间建立相等关系,则应重写此方法。如果您已经覆盖了equals(),那么覆盖方法hashCode()也是非常重要的。

实现EDCOX1 5时,建立平等是Java对象契约的一部分。如果您正在处理集合,但尚未实现hashCode(),则可能会发生奇怪的错误:

1
2
3
4
HashMap<Cat, String> cats = new HashMap<>();
Cat cat = new Cat("molly");
cats.put(cat,"This is a cool cat");
System.out.println(cats.get(new Cat("molly"));

如果没有实现hashCode(),执行前一个代码后会打印null


由于Java不支持操作符重载,= =行为相同对于除equals()之外的每个对象,都是方法,可以在Java和比较对象的逻辑可以基于业务来改变。规则。

Java中的==和相等的主要区别是:建议检查equals()方法时比较原语物体相等。

字符串比较是使用==和equals方法的常见情况。因为java.lang.string类重写等于方法,所以如果两个字符串对象包含相同的内容,但==will,则返回true只有当两个引用指向同一对象时才返回true。

下面是一个比较Java中的两个字符串的例子,使用等式= =和等式()方法来消除一些疑虑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class TEstT{

    public static void main(String[] args) {

String text1 = new String("apple");
String text2 = new String("apple");

//since two strings are different object result should be false
boolean result = text1 == text2;
System.out.println("Comparing two strings with == operator:" + result);

//since strings contains same content , equals() should return true
result = text1.equals(text2);
System.out.println("Comparing two Strings with same content using equals method:" + result);

text2 = text1;
//since both text2 and text1d reference variable are pointing to same object
//"==" should return true
result = (text1 == text2);
System.out.println("Comparing two reference pointing to same String with == operator:" + result);

}
}