当前位置:  开发笔记 > 编程语言 > 正文

在Java中覆盖equals时,为什么使用Object以外的参数不起作用?

如何解决《在Java中覆盖equals时,为什么使用Object以外的参数不起作用?》经验,为你挑选了3个好方法。

我最近遇到了一个有趣的行为.似乎如果我重写.equals()来获取除Object之外的参数,它就不会被调用.任何人都可以向我解释为什么会这样吗?这似乎违反了我对OOP中多态性的理解,但也许我错过了一些东西.

这里有更简单的代码,显示了我所看到的内容:

public class MyClass {
  private int x;
  public MyClass(int n) { x = n; }
  public boolean equals(Object o) { return false; }
  public boolean equals(MyClass mc) { return x == mc.x; }
  public static void main(String[] args) {
    List list = new ArrayList();
    list.add(new MyClass(3));
    System.out.println("Contains 3? " + list.contains(new MyClass(3)));
  }
}

运行时,它会打印" Contains 3? false".它看起来像是调用了equals(Object)函数,即使有另一个函数可以工作.相比之下,如果我写这样的equals代码按预期工作:

public boolean equals(Object o) {
  if(!(o instanceof MyClass))
    return false;
  MyClass mc = (MyClass)o;
  return x == mc.x;
}

为什么不根据参数的类型确定要调用哪个版本的函数?



1> Darron..:

你混淆了"覆盖"和"超载".

覆盖 - 为了多态而添加现有方法的替换定义.该方法必须具有相同的签名.签名由名称和参数类型组成.根据目标对象的运行时类型在运行时选择重写的方法.

重载 - 添加具有相同名称但具有不同签名的方法.根据目标对象的编译时类型,在编译时选择重载方法.



2> p3t0r..:

equals(Object)覆盖了一个超级方法; 你不能在不使用完全相同的签名的情况下覆盖超级方法(嗯,有一些例外,如协变返回类型和异常).



3> blizpasta..:

请注意,您调用的方法是在ArrayList > 的javadoc中定义的

boolean contains(Object o)
    Returns true if this list contains the specified element. 

代替

boolean contains(E o)
    Returns true if this list contains the specified element. 

ArrayList.java的实现:

private transient Object elementData[];

public boolean contains(Object elem) {
    return indexOf(elem) >= 0;
}

public int indexOf(Object elem) {
    if (elem == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (elem.equals(elementData[i]))
                return i;
    }
    return -1;
}

它使用Object超类中定义的equals方法,因为在ArrayList >的实现中没有重写equals方法.

在java中重写Object equals时,您也应该重写Object hashCode方法.

无论如何,您可能想尝试以下代码:

class A{    
    public int content;    
    A(){
        this(0);
    }    
    A(int value){
        content = value;
    }   
    public boolean equals(Object obj){
        System.out.println("overriding equals method");
        return this.content == ((A) obj).content;
    }    
    public boolean equals(A a){
        System.out.println("overloading equals method");
        return this.content == a.content;
    }    
    public static void main(String[] args){
        A x = new A(1);
        A y = new A(2);
        Object z  = new A(1);
        System.out.println(x.equals(y));
        System.out.println(x.equals(x));
        System.out.println(x.equals(z));
        //override as z is declared as Object at compile time
        //so it will use methods in class Object instead of class A
        System.out.println(x.equals((Object) y));
        System.out.println(x.equals((Object) x));        
    }   
}
//rant: they didn't teach me these in javaschool and I had to learn it the hard way.

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有