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

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

  • ==是一个引用比较,即两个对象都指向相同的内存位置
  • .equals()计算对象中值的比较
757671 次浏览

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

  • .equals(...)只会比较它要比较的东西,不多不少。
  • 如果一个类没有重写equals方法,则它默认为已重写此方法的最近父类的equals(Object o)方法。
  • 如果没有父类提供覆盖,那么它默认为最终父类Object中的方法,因此你只剩下Object#equals(Object o)方法。根据Object API,这与==相同;也就是说,它返回true当且仅当两个变量引用同一个对象,如果它们的引用是同一个。因此,你将测试对象相等而不是功能平等
  • 如果您覆盖equals,请始终记住覆盖hashCode,以免“破坏合约”。根据API,如果两个对象必须hashCode()方法显示它们是等价的,则从hashCode()方法返回的结果将是相同的。反过来是没有必然为真。

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

equals方法比较对象。

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

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

重写. equals()后你想做什么随你便。你可以将调用对象的状态与传入对象的状态进行比较,或者你可以直接调用super.equals()

请记住,.equals(...)必须由您尝试比较的类实现。否则,没有太大意义;Object类的方法版本与比较操作执行相同的操作:对象#等于

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

enum FooEnum {A, B, C}

你一次永远不会有超过一个A的实例,BC也是如此。这意味着你实际上可以这样写一个方法:

public boolean compareFoos(FooEnum x, FooEnum y)
{
return (x == y);
}

你不会有任何问题。

关于String类:

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

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

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

我希望这能把事情弄清楚一点。

==操作员equals()方法

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

根据你是在谈论“原语”还是“对象类型”,有一些小的区别;如果你谈论的是“静态”或“非静态”成员,也可以这样说;你也可以混合上述所有…

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

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


}

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

值得补充的是,对于原始类型的包装器对象-即Int、Long、Double-==如果两个值相等,则返回true。

Long a = 10L;
Long b = 10L;


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

相比之下,将上述两个Long放入两个单独的ArrayList中,equals将它们视为相同,但==不会。

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.");

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

由于Java不支持运算符重载,因此==的行为相同 对于每个对象,但equals()是方法,可以在 可以根据业务更改比较对象的Java和逻辑 规则。

==和equals在Java中的主要区别是"=="用于 比较原语,同时建议使用equals()方法检查 对象相等。

字符串比较是同时使用#EYZ0和equals()方法的常见场景。由于java.lang.String类覆盖等于方法,因此 如果两个String对象包含相同的内容但==将返回true 仅当两个引用指向同一个对象时返回true。

使用==equals()方法比较Java中的两个字符串以求相等,这将消除一些疑虑:

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


}
}

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

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

==运算符总是比较引用。但是在

equals()方法

如果我们重写equals方法,它取决于实现,而不是重写方法中给出的实现的基本对象。

 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和==也。 但是如果我们覆盖equals方法比

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

知道签出它将返回true和false对于相同的情况下,只有我们覆盖

等于方法。

它在对象的内容(id)的基础上比较对象

但是==

仍然比较对象的引用。

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

回答这个问题的最好方法是问自己几个问题。所以让我们开始吧:

下面程序的输出是什么:

String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);

如果你说,

false
true

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

true
false

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

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

下面程序的输出是什么:

String mango = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);

如果你说,

false
true

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

true
false

请比较上面的程序,并尝试考虑一下。

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

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

你能试着想想上面代码中最后三行的输出吗: 对我来说,有一个人打印了这个(您可以在此处查看代码):

false
true
true
false
mango mango
false
true
17225372
17225372
5433634

哦!现在你看到了标识HashCode(mango)等于标识HashCode(mango2)但不等于标识HashCode(mango3)

即使所有的字符串变量——mango、mango2和mango3——都有相同的值,也就是“mango”,identityHashCode()对所有人来说仍然不一样。

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

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

我不确定java在内部是如何工作的,但我假设这就是我所说的:

mango = "mango";

Java创建了一个字符串"mango",它由变量mango指向(引用),类似于

mango ----> "mango"

现在在下一行,当我说:

mango2 = "mango";

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

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

mango和mango2都指向同一个引用 当我说

mango3 = new String("mango")

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

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


mango3 ------> "mango"

这就是为什么当我输出mango == mango2的值时,它输出true。当我输出mango3 == mango2的值时,它输出false(即使值相同)。

当你取消注释// mango2 = "mang";行时 它实际上创建了一个字符串“mang”,将我们的图表变成这样:

mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"

这就是为什么标识HashCode对所有人来说都不一样的原因。

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

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

equals()是从Object类继承的方法。默认情况下,如果两个对象具有相同的引用,此方法会进行比较。这意味着:

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

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

当建立相等性是Java对象契约的一部分时实现hashCode()。如果您正在使用集合,并且您还没有实现hashCode(),可能会发生奇怪的坏事:

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

==运算符测试两个变量是否具有相同的引用 (也就是指向内存地址的指针)。

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)

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

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


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

干杯:-)

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


}
}

----Output----- 真正 虚假 true

 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 o)比较实例的hashCode()。 这就是为什么说如果你以后没有遇到惊喜,就不要破坏equals()和hashCode()之间的契约。

    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)==用于比较基元。

例如:

        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()用于比较对象。 例如:

        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

简而言之,答案是“是”。

在Java中,==运算符比较两个对象以查看它们是否指向相同的内存位置;而.equals()方法实际上比较两个对象以查看它们是否具有相同的对象值。

这里有一个关于relational operator ==the method .equals()之间区别的一般规则。

object1 == object2比较对象1和对象2引用的对象是否引用t他在堆中相同的内存位置

object1.equals(object2)比较对象1和对象2的值,无论它们在内存中的位置如何

这可以用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

情景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

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

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

因此,创建个人对象person1 and person2并使用.equals()比较这两个,我需要覆盖人力类的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;
}


}

这个类执行的结果是:

is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false

这是身份等价之间的区别。

a == b表示a和b是相同,也就是说,它们是内存中相同对象的符号。

a.equals( b )意味着它们是相当,它们是在某种意义上具有相同值的对象的符号——尽管这些对象可能在内存中占据不同的位置。

请注意,在等价的情况下,如何评估和比较对象的问题就会发挥作用——复杂的对象可能被认为是等价的,即使它们的某些内容不同。有了同一性,就没有这样的问题了。

简而言之,==检查两个对象是否指向相同的内存位置,而.equals()评估对象中的值的比较。

例1-

==和. equals方法仅用于引用比较。这意味着两个对象是否引用同一个对象。

对象类等于方法实现

public class HelloWorld{
public static void main(String []args){
Object ob1 = new Object();
Object ob2 = ob1;
System.out.println(ob1 == ob2); // true
System.out.println(ob1.equals(ob2)); // true
}
}

输入图片描述

例2-

但是如果我们想使用equals方法比较对象的内容,那么类必须覆盖对象的class equals()方法并提供内容比较的实现。在这里,String类覆盖了equals方法进行内容比较。所有包装类都覆盖了equals方法进行内容比较。

字符串类等于方法实现

public class HelloWorld{
public static void main(String []args){
String ob1 = new String("Hi");
String ob2 = new String("Hi");
System.out.println(ob1 == ob2); // false (Both references are referring two different objects)
System.out.println(ob1.equals(ob2)); // true
}
}

输入图片描述

例3-

在String的情况下,还有一个用例。在这里,当我们将任何字符串分配给String引用时,将在字符串常量池中创建字符串常量。如果我们将相同的字符串分配给新的String引用,则不会创建新的字符串常量,而是会引用现有的字符串常量。

public class HelloWorld{
public static void main(String []args){
String ob1 = "Hi";
String ob2 = "Hi";
System.out.println(ob1 == ob2); // true
System.out.println(ob1.equals(ob2)); // true
}
}

输入图片描述

请注意,每当重写此方法时,通常需要重写hashCode方法,以维护hashCode方法的一般契约,该契约规定相等的对象必须具有相等的哈希码。

Javaapi equals()方法协定

equals()方法主要比较对象的原始内容。

如果我们写

    String s1 = "Samim";
String s2 = "Samim";
String s3 = new String("Samim");
String s4 = new String("Samim");


System.out.println(s1.equals(s2));
System.out.println(s2.equals(s3));
System.out.println(s3.equals(s4));

输出将是

true
true
true

因为equals()方法比较对象的内容。 在第一System.out.println()中,s1和s2的内容是相同的,这就是为什么它打印true。 对于其他System.out.println()也是如此。

再一次,

    String s1 = "Samim";
String s2 = "Samim";
String s3 = new String("Samim");
String s4 = new String("Samim");
    

System.out.println(s1 == s2);
System.out.println(s2 == s3);
System.out.println(s3 == s4);

输出将是

true
false
false

因为==运算符主要比较对象的引用,而不是值。 在System.out.println()中,s1和s2的引用是相同的,这就是为什么它返回true。

在第二个System.out.println()中,创建了s3对象,这就是为什么会创建s3的另一个引用,并且s2和s3的引用会有所不同,因此它返回“false”。

第三个System.out.println(),遵循第二个System.out.println()的规则,这就是为什么它会返回“false”。