Java 运行时多态性不适用于不同的参数类型

Java runtime polymorphism not working with different parameter types

我有 3 个不同的 class,

public class Parent {
    public void add(double a, double b) {
        System.out.println("Parent class add(double double)");
    }

public class Child extends Parent {
    public void add(long a, long b) {
        System.out.println("Child class add(long long)");
    }
}

public class Test {
    public static void main(String arr[]) {
        Parent parent = new Child();
        parent.add((long)System.currentTimeMillis(), (long)System.currentTimeMillis());
    }
}

输出应该是 Child class add(long long),但不是这个, 它正在显示 Parent class add(double double)

但是当我在父 class 中添加子 class 的添加方法时,它是 显示正确的输出。谁能告诉我原因。

你不是overridingChildclass中的方法。你是overloading继承自Parentclass的方法。 Runtime polymorphism 仅适用于子class 中的重写方法,不适用于重载形式。

发生这种情况的解释如下:

  1. Child class 继承了 public add 方法,该方法接受两个 double 参数。即使您在代码中看不到它,子 class 实际上包含一个 public add 方法,它接受两个 double 个参数。
  2. 当您在 Child 中定义一个名为 add 的方法并接受两个 long 参数时,您实际上是在重载继承的 add 方法,该方法接受两个 double 参数。
  3. 由于 run-time polymorphism 仅适用于 runtime,编译器在编译时不知道 Child class 重载了 add 方法取而代之的是两个 long 参数。在运行时,JVM 将简单地将调用分派给继承的 add 方法,该方法接受两个 double 参数,因为这是 Child class 覆盖的方法。

您应该始终在您认为要从父 class 覆盖的方法上方添加 @Override 注释。这有两个优点

  1. 当您查看一个方法时,您马上就会知道它正在覆盖超 class 中的一个方法。
  2. 如果父 class 不包含具有相似签名的方法,您会立即收到编译错误。

使用超类引用时不能访问子类的方法。所描述的行为是预期的,因为 Parent 中没有方法 add(long, long),只有方法 add(double, double)(因此,您不会覆盖,但会在 [= 中重载 add 14=]).

问题是选择了要调用的方法签名at compile time。编译器只知道 parentParent 类型,所以唯一兼容的签名是 add(double, double),因为两个 long 都可以扩展为 double .

Child方法add(long, long)是重载,不是覆盖,所以Child继承了add(double, double)方法,并调用了

如果您将 add(long, long) 方法添加到 Parent class,那么它将是一个精确匹配,它将通过 add(double, double) 方法被调用。

你在这里超载而不是覆盖。因此,当您 运行 针对 Parent.add(double,double) 执行的代码时,您的长参数被扩大为双精度。

http://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.5