Java多态和运行时方法匹配

时间:2018-11-01 20:25:43

标签: java polymorphism runtime

例如,我有以下代码。

class Circle {
    double radius;

    public boolean equals(Object circle) {
        return this.radius ==((Circle)circle).radius;
    }
}

还有司机

public class Driver {
    public static void main(String[] args) {
        Object circle1 = new Circle();
        Circle circle2 = new Circle();
        System.out.println(circle1.equals(circle2));

    }
}

它显示True,但是如果我将Circle.equals()重写为

public boolean equals(Circle circle) {
    return this.radius ==((Circle)circle).radius;
}

其中.equals()方法采用Circle类型,系统将输出False。
我知道Circle类是Object类的子类,因此编译器不会报告错误,并且在运行时,JVM选择正确的重写方法来实现正确的行为。 如果我将代码修改为最低代码,.equals()接受Circle类对象,则代码可以正确实现,请告诉我原因。预先感谢。

2 个答案:

答案 0 :(得分:3)

带有方法签名

public boolean equals(Circle circle) {

您正在超载 equals,而不是覆盖它;这不是编译器错误。这意味着Circle将继承Object的{​​{1}}实现,该实现只是比较对象引用以查看它们是否相等。这将返回equals

您的false方法应使用equals才能正确覆盖该方法。您还应该使用Object注释,如果带注释的方法未覆盖超类中的方法,则它将产生编译器错误。 method主体应在强制转换之前测试其参数是否为该类的实例,以便它可以返回@Override而不是抛出false

此外,如果您要覆盖ClassCastException,那么最好覆盖hashCode

答案 1 :(得分:2)

在Java中,返回类型是协变的,这意味着您可以将子类用作重写方法的返回类型。
例如,这是有效的:

public class Foo{
    @Override
    public Foo clone(){
        ...
    }
}

但是参数类型不是协变的。因此,您可以在第二个代码中重载该方法,而不用覆盖它。

@Override注释该方法,它将不再编译:

@Override 
public boolean equals(Circle circle) {
    return this.radius ==((Circle)circle).radius;
}