【问题标题】:What is the difference between == and equals() in Java?Java中==和equals()有什么区别?
【发布时间】:2011-11-23 03:23:31
【问题描述】:

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

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

【问题讨论】:

  • 是的,差不多
  • 是的,准确。您可以将.equals() 视为有意义的等价
  • 像“两个对象都指向同一个内存位置”这样的句子是草率的语言,这会使理解更加困难。您的意思是:“两个变量都引用同一个对象”。请注意,变量不是对象;变量是对象的引用。对象不“指向”任何东西。

标签: java identity equality object-comparison


【解决方案1】:

一般来说,您的问题的答案是“是”,但是...

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

【讨论】:

  • 如果 == 检查内存引用,那么为什么我会在 [this][1][1] 中出现这种奇怪的行为:docs.google.com/document/d/… 我希望输出为真。可以消除我的困惑
  • @JSK 打印 d1 和 d2 的值,我想你会明白为什么返回 false。
  • @BoDidely 我想通了。这是因为所有的包装类都是不可变的。
  • The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
    Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes. (docs.oracle.com/javase/7/docs/api/java/lang/…)
  • 无关:今天我提出了一个元问题 (meta.stackoverflow.com/questions/372795/…),在评论低质量的新手问题时,关于良好/有效/...“自动”消息。我收到的反馈几乎感觉是“你在做完全错误的事情”。现在我只是想知道你怎么看这个?您的 quiver 中是否有“通用”消息,或者在这种情况下您是否只编写特定的 cmets?
【解决方案2】:

关于String类:

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

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

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

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

【讨论】:

  • 所以对于字符串 == 引用也等于?即与其他对象一样工作吗?
  • (线程死灵术,我知道...)对于Strings,== 也是引用等于,是的,但它通常有效(如在两个具有相同内容的Strings 将通常彼此为==),因为Java 如何处理Strings。并非总是如此,这当然是不好的做法,但这是一个常见的错误,尤其是来自其他语言的人。
  • 补充托尼奥的评论。 String 从字符串文字构建将被添加到称为 String constant pool 的东西中,例如String s1 = "someString"; String s2 = "someString;" s1s2 将共享相同的引用。 s1 == s2 将返回 true。但是如果它们是通过String constructor 构建的,例如String s1 = new String("someString"); String s2 = new String("someString"); 那么他们将不会共享相同的引用。 s1 == s2 将返回 false。
【解决方案3】:

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

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

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 类中的方法)的解释:

【讨论】:

  • 有趣的例子。与上述答案不同的观点。谢谢!
  • 在我看来最好的答案,因为它比其他全文答案更清晰而不会失去解释(当然,如果你理解类和静态概念)
【解决方案4】:

== 和 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

请对比一下上面的程序,试着想一想。

好的。现在这可能会有所帮助(请阅读:print the address of object - 不可能,但我们仍然可以使用它。)

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 将其打印出来 (you can check the code here):

false
true
true
false
mango mango
false
true
17225372
17225372
5433634

哦!现在你看到 identityHashCode(mango) 等于 identityHashCode(mango2) 但它不等于 identityHashCode(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"

这就是为什么每个人的identityHashCode都不一样。

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

【讨论】:

  • 发生mango == mango2 是不是因为您没有将mango2 创建为新的String 对象,而是直接引用了"mango"
  • 使用 String 来清除对 == 和 equals 的疑问的错误示例,不与 new 一起使用的 String 被放入字符串池中,并且每当将相同的字符串分配给新的引用时,它都指向池中的相同字符串。所以可能使用一些自定义对象示例进行 == 和 .equals() 比较。
【解决方案5】:

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

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)

干杯:-)

【讨论】:

  • 错了。 if(foo==bar) 这应该是真的而不是假的。它将重用相同的字符串“adc”。在沙箱中测试,两者都会返回 true。
  • @JohnathanLogan 我猜它是由于字符串实习。现在我已更改为“new String("abc")”。希望现在不会有任何问题。感谢您的告知。
  • 您的答案仅对 String 对象有效,因为如果“表示相同的字符序列”,则 String 覆盖等于返回 true。 docs.oracle.com/javase/7/docs/api/java/lang/String.html对于原始问题的一般情况,您的答案要么错误,要么误导,要么不正确
【解决方案6】:

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

equals 方法比较对象。

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

【讨论】:

    【解决方案7】:

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

    运算符一般用于primitive类型比较,因此==用于内存地址比较,equals()方法用于比较对象

    【讨论】:

    • 简单易行的答案
    【解决方案8】:

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

    覆盖 .equals() 后,您希望做什么。您可以将调用对象的状态与传入对象的状态进行比较,或者您可以调用 super.equals()

    【讨论】:

      【解决方案9】:
       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
      

      【讨论】:

      • 简单最好的解释
      【解决方案10】:

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

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

      enum FooEnum {A, B, C}
      

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

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

      你不会有任何问题。

      【讨论】:

        【解决方案11】:

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

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

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

        这可以用字符串很好地证明

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

        【讨论】:

          【解决方案12】:

          在评估代码时,很明显 (==) 是根据内存地址进行比较,而 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
              */
          

          【讨论】:

            【解决方案13】:

            == 和 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
            

            【讨论】:

              【解决方案14】:

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

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

              【讨论】:

                【解决方案15】:

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

                的情况下

                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 对象都包含相同的数据,但引用不同,所以 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
                    }
                 }
                

                知道检查它会返回 true 和 false 对于相同的情况,只有我们覆盖了

                等于方法。

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

                但是 ==

                仍然比较对象的引用。

                【讨论】:

                  【解决方案16】:

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

                  【讨论】:

                    【解决方案17】:
                    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");
                        }
                    
                        }
                      }
                    

                    ----输出----- 真的 错误的 真的

                    【讨论】:

                      【解决方案18】:

                      对于原始类型(即 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.");
                      

                      【讨论】:

                      • 原始类型的包装器对象 - 即 Integer、Long、Double == 即使两个值相等也可能不会返回 true。它完全取决于 Wrapper 的缓存。下面的代码将打印 false,因为默认缓存限制为 -128 到 127。Long a = 128l; Long b = 128l; System.out.println(a == b);
                      【解决方案19】:

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

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

                      字符串比较是同时使用==equals()方法的常见场景。由于java.lang.String类覆盖了equals方法,它 如果两个 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);
                      
                          }
                          }
                      

                      【讨论】:

                        【解决方案20】:

                        String pool(又名interning)和Integer pool进一步模糊了区别,在某些情况下可能允许您将== 用于对象而不是.equals p>

                        这可以为您提供更高的性能 (?),但代价是更高的复杂性。

                        例如:

                        assert "ab" == "a" + "b";
                        
                        Integer i = 1;
                        Integer j = i;
                        assert i == j;
                        

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

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

                        【讨论】:

                          【解决方案21】:

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

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

                          【讨论】:

                            【解决方案22】:

                            示例 1 -

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

                            Object class equals method implementation

                            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 方法比较对象的内容,那么类必须重写对象的类 equals() 方法并提供内容比较的实现。在这里,String 类重写了用于内容比较的 equals 方法。所有包装类都覆盖了用于内容比较的 equals 方法。

                            String class equals method implementation

                            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 -

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

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

                            Java API equals() method contract

                            【讨论】:

                              【解决方案23】:

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

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

                              null如果没有实现hashCode()会在执行之前的代码后打印出来。

                              【讨论】:

                                【解决方案24】:

                                这是同一性等价性的区别。

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

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

                                请注意,使用等价时,如何评估和比较对象的问题就开始发挥作用了——即使复杂对象的某些内容不同,实际上也可以将复杂对象视为等价。有了身份,就不存在这样的问题了。

                                【讨论】:

                                  【解决方案25】:

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

                                  【讨论】:

                                    猜你喜欢
                                    • 2022-12-04
                                    • 2011-12-02
                                    • 1970-01-01
                                    • 2011-10-09
                                    • 2010-12-11
                                    • 1970-01-01
                                    相关资源
                                    最近更新 更多