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

Java中==和equals()之间的区别是什么?,java,identity,equality,object-comparison,Java,Identity,Equality,Object Comparison,我想澄清我是否正确理解了这一点: ==是一个参考比较,即两个对象指向相同的内存位置 .equals的计算结果与对象中的值进行比较 一般来说,你的问题的答案是肯定的,但是 .等于。。。只会比较它所写的内容,不多不少。 如果一个类不重写equals方法,那么它默认为重写此方法的最近父类的equalsObject方法。 如果没有父类提供重写,那么它默认为最终父类Object中的方法,因此只剩下objectequalso对象方法。根据对象API,这与==;也就是说,当且仅当两个变量引用同一个对象时,如果

我想澄清我是否正确理解了这一点:

==是一个参考比较,即两个对象指向相同的内存位置 .equals的计算结果与对象中的值进行比较
一般来说,你的问题的答案是肯定的,但是

.等于。。。只会比较它所写的内容,不多不少。 如果一个类不重写equals方法,那么它默认为重写此方法的最近父类的equalsObject方法。 如果没有父类提供重写,那么它默认为最终父类Object中的方法,因此只剩下objectequalso对象方法。根据对象API,这与==;也就是说,当且仅当两个变量引用同一个对象时,如果它们的引用是一个且相同的,则返回true。因此,您将测试对象相等,而不是函数相等。 如果重写equals,请始终记住重写hashCode,以免违反合同。根据API,如果两个对象的equals方法显示它们是等价的,则从hashCode方法返回的结果必须相同。反之不一定正确。
您必须重写equals函数和其他函数才能将其用于自定义类

equals方法比较对象


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

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

这是你的愿望,一旦你放弃,你想做什么。您可以将调用对象的状态与传入对象的状态进行比较,也可以只调用super.equals

记住.equals。。。必须由您试图比较的类实现。否则,就没有什么意义了;对象类的方法版本执行与比较操作相同的操作:

只有在比较枚举时,才真正希望对对象使用比较运算符。这是因为一次只有一个枚举值实例。例如,给定枚举

enum FooEnum {A, B, C}
一次不会有多个A实例,B和C也是如此。这意味着您可以编写如下方法:

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

您将不会遇到任何问题。

关于字符串类:

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

另一方面,==运算符比较两个对象引用的值,以查看它们是否引用同一个字符串实例。如果两个对象引用的值引用同一个字符串实例,则布尔表达式的结果将为true..duh。另一方面,如果两个对象引用的值引用不同的字符串实例,即使两个字符串实例具有相同的值,也就是说,每个字符串实例的字符数组的内容相同,则布尔表达式的结果将为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和逻辑 规则

Java中==和equals之间的主要区别在于==用于 比较原语,同时建议使用equals方法进行检查 对象的相等性

字符串比较是使用 ==和等于方法。由于java.lang.String类重写等于方法,因此 如果两个字符串对象包含相同的内容,但==will,则返回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通常包含==用于测试,因为如果要测试两个对象是否相等,这是您希望测试的第一件事


And==实际上会查看基本类型的值,对于对象,它会检查引用。

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

相等法

这取决于实现,若我们被覆盖等于方法,那个么它会根据覆盖方法中给出的实现来比较对象

 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对象都包含相同的数据,但引用不相同,所以equals返回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
    }
 }
知道check out对于相同的情况,它将返回true和false,只有我们重写了它

等于方法

它基于对象的contentid来比较对象

但是==

仍然比较对象的引用。

aka并进一步模糊差异,并且在某些情况下允许您对对象使用==而不是.equals

这可以提供更高的性能,但代价是更高的复杂性

例如:

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

assert new String("a") != new String("a");

Integer i = 128;
Integer j = 128;
assert i != j;
我建议您远离这种微观优化,始终对对象使用.equals,对基本体使用==:

assert (new String("a")).equals(new String("a"));

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

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

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

以下程序的输出是什么:

如果你说

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

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

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

以下程序的输出是什么:

现在如果你说

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));
你能不能试着想想上面代码中最后三行的输出: 对于我来说,ideone打印了以下内容:

哦!!现在您看到identityHashCodemango等于identityHashCodemango 2,但它不等于identityHashCodemango 3

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

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

我们知道如果hashcodex=N,hashcodey=N=>x等于y

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

mango = "mango";
mango2 = "mango";
java创建了一个字符串mango,它被变量mango指向引用,如下所示

mango ----> "mango"
mango ----> "mango" <---- mango2
下一行我说:

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

mango ----> "mango"
mango ----> "mango" <---- mango2
它实际上为mango创建了一个全新的referencestring。看起来像这样

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

mango3 ------> "mango"
这就是为什么identityHashCode对所有人都不一样

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

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

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

object1.EqualObject2 object1==object2

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

当建立相等性是Java对象契约的一部分时,实现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

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

而equals方法测试两个变量是否引用对象 具有相同的状态 卢埃斯

干杯:-

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

    }
  }
--输出--- 符合事实的 错误的
true

当您计算代码时,很明显==根据内存地址进行比较,而equalsObject则比较实例的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等于用于比较对象。 例如:

        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方法实际上是比较这两个对象,看看它们是否具有相同的对象值。

这里有一个关于关系运算符==和.equals方法之间差异的一般经验

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

object1.EqualObject2比较object1和object2的值,而不管它们位于内存中的什么位置

这可以用字符串很好地演示

情景1

情景2

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

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

因此,创建person对象person1和person2,并使用.equals比较这两个对象,我需要重写person类的equals方法,以定义比较将基于哪个实例变量H或权重

但是,==运算符仍将根据两个objectsperson1和person2的内存位置返回结果

为了简化这个person对象比较,我创建了以下测试类。对这些概念进行实验将揭示大量事实

该类执行的结果是:

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、 等于b意味着它们是等价的,它们是在某种意义上具有相同值的对象的符号——尽管这些对象在内存中可能占据不同的位置

注意,对于等价性,如何评估和比较对象的问题开始发挥作用——复杂对象在实际应用中可能被视为等价的,即使它们的某些内容不同。对于identity,没有这样的问题。

简单地说,==检查两个对象是否指向相同的内存位置,而.equals的计算结果是对象中值的比较。

示例1-

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

例2-

但若我们想使用equals方法比较对象的内容,那个么类必须重写对象的class equals方法,并提供内容比较的实现。这里,String类重写了用于内容比较的equals方法。所有包装器类都重写了用于内容比较的equals方法

例3-

对于字符串,还有一个用例。这里,当我们将任何字符串指定给字符串引用时,字符串常量将在字符串常量池中创建。若我们将相同的字符串分配给新的字符串引用,则不会创建新的字符串常量,而会引用现有的字符串常量

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方法的一般约定,即相等的对象必须具有相等的哈希代码


是的,相当多,非常准确。你可以把.equals想象成有意义的等价。像两个物体指向同一记忆位置一样,句子的可能重复是草率的语言,这会使理解更加困难。你的意思是:两个变量都指向同一个对象。请注意,变量不是对象;变量是对对象的引用。对象不指向任何东西。所以对于字符串==引用是否也等于?ie和其他物体的效果一样?我知道线程巫术。。。对于字符串,==也是reference equals,是的,但它通常在两个具有相同内容的字符串中工作,因为Java处理字符串的方式,它们之间通常是==的。这并不总是,这当然是一种不好的做法,但这是一种常见的错误,特别是来自其他语言的人。从字符串文本生成的字符串将添加到称为字符串常量池的内容中,例如字符串s1=someString;字符串s2=someString;s1和s2将共享相同的引用。s1==s2将返回true。但如果它们是通过
字符串构造函数,例如字符串s1=新的StringsomeString;字符串s2=新的StringsomeString;那么它们就不会共享相同的引用。s1==s2将返回false。有趣的示例。从不同的角度来看上述答案。谢谢在我看来,最好的答案是,如果你理解了类和静态概念,那么它比其他全文答案更清晰,而且不会丢失解释。当然,如果==检查内存引用,那么为什么我在[this][1][1]中会出现这种奇怪的行为:我希望输出是真的。我可以清除我的confusions@JSK打印出d1和d2的值,我想你就会明白为什么返回false了。@BoDidely,我算出来了。这是因为所有的包装器类都是不可变的,类对象的equals方法实现了对象上最有区别的等价关系;也就是说,对于任何非空引用值x和y,当且仅当x和y引用同一对象x==y的值为true时,此方法才返回true。请注意,每当重写hashCode方法时,通常都需要重写该方法,以便维护hashCode方法的一般约定,即相等的对象必须具有相等的哈希代码。无关:今天我提出了一个关于好/有效/的元问题。。。评论低质量新手问题时自动发送消息。我收到的反馈几乎让我觉得你做了一件完全错误的事情。现在我只是想知道你是怎么看的?你的箭袋里有一般的信息吗,或者在这种情况下你只写具体的评论吗?错。iffoo==bar这应该是true而不是false。它将重复使用相同的字符串adc。在沙箱中测试,两个都会返回真值。@JohnathanLogan我想这是因为字符串实习。现在我换成了新的ABC。希望现在不会有任何问题。谢谢通知。您的答案仅对字符串对象有效,因为如果表示相同的字符序列,字符串重写等于返回true。对于原始问题的一般情况,您的答案可能是错误的、误导性的或不正确的mango==mango2是否因为您没有将mango2创建为新的String对象,而是直接引用了mango?使用String消除对==和equals的疑问的错误示例,当不与new一起使用时,字符串被放入字符串池,并且每当相同的字符串被分配给新引用时,它都指向池中的相同字符串。因此,可能会对==和.equals比较使用一些自定义对象示例。对于基本类型(即Integer、Long、Double==),简单且最佳的explanationWrapper对象可能不会返回true,即使这两个值相等。它完全取决于包装器的缓存。下面的代码将打印为false,因为默认缓存限制为-128到127。长a=128l;长b=128l;System.out.printlna==b;
    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
    */
        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
        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
 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 
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
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
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
     }    
}
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
     }
}
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
     }
}