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 的添加方法时,它是
显示正确的输出。谁能告诉我原因。
你不是overriding
Child
class中的方法。你是overloading
继承自Parent
class的方法。 Runtime polymorphism
仅适用于子class 中的重写方法,不适用于重载形式。
发生这种情况的解释如下:
-
Child
class 继承了 public
add
方法,该方法接受两个 double
参数。即使您在代码中看不到它,子 class 实际上包含一个 public
add
方法,它接受两个 double
个参数。
- 当您在
Child
中定义一个名为 add
的方法并接受两个 long
参数时,您实际上是在重载继承的 add
方法,该方法接受两个 double
参数。
- 由于
run-time polymorphism
仅适用于 runtime
,编译器在编译时不知道 Child
class 重载了 add
方法取而代之的是两个 long
参数。在运行时,JVM 将简单地将调用分派给继承的 add
方法,该方法接受两个 double
参数,因为这是 Child
class 覆盖的方法。
您应该始终在您认为要从父 class 覆盖的方法上方添加 @Override
注释。这有两个优点
- 当您查看一个方法时,您马上就会知道它正在覆盖超 class 中的一个方法。
- 如果父 class 不包含具有相似签名的方法,您会立即收到编译错误。
使用超类引用时不能访问子类的方法。所描述的行为是预期的,因为 Parent
中没有方法 add(long, long)
,只有方法 add(double, double)
(因此,您不会覆盖,但会在 [= 中重载 add
14=]).
问题是选择了要调用的方法签名at compile time。编译器只知道 parent
是 Parent
类型,所以唯一兼容的签名是 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
我有 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 的添加方法时,它是 显示正确的输出。谁能告诉我原因。
你不是overriding
Child
class中的方法。你是overloading
继承自Parent
class的方法。 Runtime polymorphism
仅适用于子class 中的重写方法,不适用于重载形式。
发生这种情况的解释如下:
-
Child
class 继承了public
add
方法,该方法接受两个double
参数。即使您在代码中看不到它,子 class 实际上包含一个public
add
方法,它接受两个double
个参数。 - 当您在
Child
中定义一个名为add
的方法并接受两个long
参数时,您实际上是在重载继承的add
方法,该方法接受两个double
参数。 - 由于
run-time polymorphism
仅适用于runtime
,编译器在编译时不知道Child
class 重载了add
方法取而代之的是两个long
参数。在运行时,JVM 将简单地将调用分派给继承的add
方法,该方法接受两个double
参数,因为这是Child
class 覆盖的方法。
您应该始终在您认为要从父 class 覆盖的方法上方添加 @Override
注释。这有两个优点
- 当您查看一个方法时,您马上就会知道它正在覆盖超 class 中的一个方法。
- 如果父 class 不包含具有相似签名的方法,您会立即收到编译错误。
使用超类引用时不能访问子类的方法。所描述的行为是预期的,因为 Parent
中没有方法 add(long, long)
,只有方法 add(double, double)
(因此,您不会覆盖,但会在 [= 中重载 add
14=]).
问题是选择了要调用的方法签名at compile time。编译器只知道 parent
是 Parent
类型,所以唯一兼容的签名是 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