【问题标题】:why equals() method when we have == operator? [duplicate]当我们有 == 运算符时,为什么要使用 equals() 方法? [复制]
【发布时间】:2011-02-15 21:31:39
【问题描述】:

当我看到equals() 方法的实现时,它只做与== 相同的操作。所以我的问题是,当我们有 == 操作符时,有什么需要把它作为单独的方法来做同样的工作?

【问题讨论】:

    标签: java equals referenceequals


    【解决方案1】:

    您不能重载== 运算符,但如果您希望equals(Object) 的行为与== 运算符不同,您可以覆盖== 运算符,即不比较引用而是实际比较对象(例如,使用全部或部分他们的领域)。

    另外,如果您确实覆盖了equals(Object),请同时查看hashCode()。这两种方法需要兼容(即根据equals(Object)相等的两个对象需要有相同的hashCode()),否则会出现各种奇怪的错误(例如将对象添加到集合或映射时)。

    【讨论】:

    • +1 你的答案更有可能。
    • 正确 - 如果您要实例化两个具有相同字段的单独对象并将这些字段在两个对象上设置为相同,则相等性测试仍将返回 false。如果您要在类上覆盖 Equals(),那么您可以测试字段并在它们相同时返回 true。
    • 平等与身份不同。两张十美元纸币是相等的(在货币模型的范围内),但它们不是同一张纸币。
    • 同意 - 这就是为什么必须手动覆盖标准相等行为以在必要时实现这一点。
    • 我不明白你为什么要谈论覆盖。在问题的上下文中,我发现它无关紧要(对不起)。正如在其他答案中所说, == 比较对象引用,而 equals() 比较对象内容。
    【解决方案2】:

    ==比较对象references,并询问两个reference是否相同。

    equals() 比较对象内容,并询问对象是否代表相同的概念。

    【讨论】:

    • 除非你在比较值类型...
    • @David:Java 中没有“值类型”之类的东西,除非您在谈论原始值。
    • 对不起 - 我的意思是原语和不能在 Java 中创建值类型的好处。
    • 但是原语没有equals()函数,只有itr自动装箱类型有它。然后结果也将是相等的,例如数字是
    • @david:我认为原语没有方法是不言而喻的,因此任何明智的人都应该做出这种区分。
    【解决方案3】:

    "string" == "string" 将返回 false "string".equals("string") 将返回 true

    使用 o1 == o2 您比较对象 1 与 o2 是同一个对象(通过引用)

    使用 o1.equals(o2),取决于对象,equals 方法会被覆盖,而不是用“return o1 == o2”之类的东西来实现

    例如,您创建 2 个 Set 实例 这 2 个集合对象是 2 个不同的对象,您可以在其中任何一个对象中添加不同的元素。 set1 == set2 将始终返回 false 但是如果 set2 包含与 set1 完全相同的元素,那么 set1.equals(set2) 最终将返回 true...并且因为在 Set 类中覆盖了 equals 方法...

    Set 的 Equals 实现是:

          public boolean equals(Object o) {
            if (o == this)
               return true;
    
            if (!(o instanceof Set))
                 return false;
            Set s = (Set) o;
            if (s.size() != c.size())
                 return false;
            return containsAll(s); // Invokes safe containsAll() above
        }
    

    【讨论】:

    • 我怀疑你的意思是 string1 == string2string1.equals(string2)——你的答案中的两个例子都会返回 false。
    • 对不起,我的意思是“string”==“string”和“string”.equals(“string”)
    • "string" == "string" 实际上会计算为真。
    【解决方案4】:

    这样做是为了让这成为可能:

    String s1 = new String("foo");
    String s2 = new String("foo");
    
    System.out.println(s1 == s2); // false?! Different references!
    System.out.println(s1.equals(s2)); // true
    

    如果您检查String#equals() 的来源,您会发现它已经适当地覆盖了Object#equals() 以比较彼此的内部字符数组(实际 值)。许多其他类也重写了此方法。

    【讨论】:

      【解决方案5】:

      两者之间有一个非常重要的区别。

      "==" 比较对象实例。默认的 equals() 实现也这样做。请运行并分析以下代码示例:

      public class Person{
         String name;
      
         public Person(String name){
             this.name = name;
         }
      
      //overriding equals
      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( name == null ) {
                  if( other.name != null )
                  return false;
          } else if( !name.equals( other.name ) )
              return false;
          return true;
          }
           }
      
          ...
          ...
          Person john1 = new Person("John");
          Person john2 = new Person("John");
          System.out.println("john1 == john2:" + (john1 == john2));
          System.out.println("john1.equals(john2):" + john1.equals(john2));
      

      如您所见,"==" 将返回 false(对象是 Person 的两个不同实例),而 equals 将返回 true(因为我们定义了两个同名的 Person 相等)

      【讨论】:

        【解决方案6】:

        对于原语== 运算符会检查两个是否相同。
        如果它不是原语,它会检查它是否是两个指针(或引用指向一个对象的同一个实例。

        equals() 方法使用== 执行自定义检查,即在Object 检查引用。但在其他类中,有时equals() 会被覆盖(我不知道这是否是正确的过去分词)equals() 必须检查内容

        所以,例如:

        int i0 = 34;
        int i1 = 34;
        int i2 = 35;
        // results
        i0 == i1: true
        i1 == i0: true
        i2 == i0: false
        

        但是如果我们有非原始人

        String str0 = new String("Hello man!");
        String str1 = new String("Hello man!");
        String str2 = new String("!nam olleH");
        String str2copy = str2;
        // Results
        str0 == str1: false // Pointer to two different object, so == will give false
        str1 == str2: false // Idem
        str2 == str2copy: true // So this are two pointers to the same object
        str0.equals(str1): true // This are not the same objects, but they are equal
        str1 == str1: true // Again: two times a pointer to the same  object
        

        那么,为什么str0.equals(str1) 返回true?因为 String 类具有 equals() 的覆盖。在该方法中,它不会通过执行return this == obj; 来检查它们是否相等,但在该方法中,会进行全面检查。我不知道他们使用哪种方法来比较两个字符串,但这里有两种可能的方法:

        • 从这两个字符串生成一个哈希码并检查它们是否相等 (int == int)
        • 逐个字符检查是否相同。

        所以我希望现在清楚了。

        【讨论】:

        • 这是一个很好的总结。正如使用字符串文字时的进一步说明,行为再次不同...... String str0 = "Hello man!"; String str1 = "你好,伙计!"; str0 == str1;当 JVM 将字面字符串对象放入字符串池中时,将返回 true。因此 str1 和 str2 都引用池中的同一个对象。
        • 吹毛求疵,但根据定义,两个值永远不会相同(否则,它只会是一个值)。
        【解决方案7】:

        == 运算符用于比较引用。
        equals() 方法是在对象定义之上定义的。

        Dog d =new Dog();
        Collar c =new Collar("Red");
         d.setCollar(c);
        Dog d2=new Dog();
         Collar c2=new Collar("Red");
        d2.setCollar(c2);
        
         d2.getCollar() ==d.getCollar()
        

        将返回 false,表示 两只狗有两个不同的项圈对象(项目)。它们不共享同一个项圈

        d2.getCollar().equals(d.getCollar())
        

        如果衣领被定义为 [如果衣领的颜色相同,衣领相同],则返回 true 两只狗的项圈颜色相同。

           class Collar{
            String color="";
            public Collar(String p0){
            this.color=p0;
            }
            boolean equals(Object c){
              Collar other=(Collar)c;
              return  this.color.equals(other.getColor());
            }
        
            public String getColor(){
              return this.color;
            }
            }
        

        【讨论】:

          【解决方案8】:

          在java中,如果操作数是原始数据类型,则等于运算符(==)对两个变量的数据进行操作。但是如果操作数是对象,java 会使用引用来比较它们,因为它无法确定在对象的哪个或哪些字段上进行比较。

          所以只有一种方法可以基于用户定义的字段进行比较,并且通过覆盖 equals() 方法在对象中定义,因为在 java 中不能覆盖 equals operator(==),因为 java 不支持运算符覆盖。

          例如,如果您想根据名称比较 Employee,您需要通过覆盖 Employee 类中的 equals 方法来定义其逻辑,如下所示:

          public class Employee {
              private Integer id;
              private String name;
          
              @Override
              public boolean equals(Object obj) {
                  Employee other = (Employee) obj;
                  if (name == null) {
                      if (other.name != null)
                          return false;
                  } else if (!name.equals(other.name))
                      return false;
                  return true;
              }
          
              public Integer getId() {
                  return id;
              }
              public void setId(Integer id) {
                  this.id = id;
              }
              public String getName() {
                  return name;
              }
              public void setName(String name) {
                  this.name = name;
              }
          
          
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-12-14
            • 2014-07-02
            • 2015-06-09
            • 1970-01-01
            • 2017-06-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多