equals()一般契约的哪一部分我的等于()不满足

时间:2015-04-15 04:18:24

标签: java eclipse equals

我对java很新,我只是想了解@Overrideequals()方法的hashcode()
我知道equals方法是正确的,它需要是:

  1. 自反: a.equals(a)
  2. 对称: a.equals(b) 然后 b.equals(a)
  3. 传递: a.equals(b) && b.equals(c) 然后 a.equals(c)
  4. 非空: ! a.equals(null)
  5. 我正在努力确定上述哪些属性,并且在编写equals方法时,我并不满意。

    我知道eclipse可以为我生成这些,但是因为我还没有完全理解这个概念,所以写出来有助于我学习。

    我已经写出了我认为正确的方法,但是当我查看eclipse生成的版本时,我似乎错过了'某些方面。

    示例:

    public class People {
    
        private Name first; //Invariants --> !Null, !=last
        private Name last;  // !Null, !=first
        private int age;    // !Null, ! <=0
        ...
    }
    

    我写的内容:

    public boolean equals(Object obj){
        if (obj == null){
            return false;
        }
        if (!(obj instanceof People)){
             return false;
        }
        People other = (People) obj;
        if (this.age != other.age){
            return false;
        }
        if (! this.first.equals(other.first)){
            return false;
        }
        if (! this.last.equals(other.last)){
            return false;
        }
        return true;
    }
    

    vs eclipse生成

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
    
        People other = (People) obj;
        if (first == null) {
            if (other.first != null)
                return false;
        } else if (!first.equals(other.first))
            return false; 
        if (age != other.age)
            return false;
        if (last == null) {
            if (other.last != null)
                return false;
        } else if (!last.equals(other.last))
            return false;
    
        return true;
    }
    

    我失踪了:

    • if (this == obj)
          return true;
      
    • if (getClass() != obj.getClass())
          return false;
      
    • 并为每个变量:

      if (first == null) {
          if (other.first != null)
              return false;
      } else if (!first.equals(other.first))
          return false;
      

    我不确定getClass()是什么,我的诽谤是不正确的?

3 个答案:

答案 0 :(得分:8)

第一段代码:

if (this == obj)
    return true;

如果您将对象引用与自身进行比较,这可以提高性能。示例:a.equals(a);

第二段代码:

if (getClass() != obj.getClass())
    return false;

这比较了被比较的引用的类是否是this的同一类。使用此方法与instanceof之间的区别在于,在与子类进行比较时,它的限制性更强。例如:

public class Foo { }
public class Bar extends Foo { }

//...
Foo foo = new Bar();
System.out.println(foo instanceof Bar); //prints true
System.out.println(foo instanceof Foo); //prints true
Foo foo2 = new Foo();
System.out.println(foo.getClass() == foo2.getClass()); //prints false

你应该选择哪一个?没有好的或坏的方法,这取决于你想要的设计。

第三段代码:

if (first == null) {
        if (other.first != null)
            return false;
    } else if (!first.equals(other.first))
        return false; //For each variable.

这只是对类中每个对象引用字段的空检查。请注意,如果this.firstnull,则执行this.first.equals(...)会抛出NullPointerException

答案 1 :(得分:4)

我认为您的实施不正确,但有一些注意事项:

if (this == obj)
      return true;

是性能优化,它直接测试a a的参考相等和短路测试。

if (getClass() != obj.getClass())
        return false;

与您的instanceof调用相似,优化掉空检查。其他调用似乎是空检查。

答案 2 :(得分:3)

你不需要写

if (obj == null){
        return false;
}
if (!(obj instanceof People)){
     return false;
}

因为null始终在false次检查中提供instanceof。所以这些行可以简化为

if (!(obj instanceof People)){
     return false;
}

关于您的方法是否符合equals()方法要求的主要问题,严格来说答案是否定的,或者至少它可能是狡猾的。这是因为可以按如下方式扩展类

public class SpecialPeople extends People {

    // code omitted

    @Override
    public boolean equals(Object object) {
        if (object == null || object.getClass() != getClass())
            return false;
        SpecialPeople other = (SpecialPeople) object;
        return other.getAge() == getAge() 
                && other.getFirst().equals(getFirst()) 
                && other.getLast().equals(getLast());
}

现在假设aPeople的实例,而bSpecialPeople的实例。假设ab具有相同的名称和年龄。然后

a.equals(b) == true  // instanceof check succeeds
b.equals(a) == false // getClass() check fails

因此equals()不对称!因此,如果您在instanceof中使用getClass()而不是equals(),则应该使用equals()方法final或类final }。