我正在为考试而学习,我需要一些帮助来理解以下代码片段中发生的事情。
class A {
public void method1(A X) {
System.out.println("A");
}
}
class B extends A {
public void method2() {
System.out.println("B");
}
}
class C extends B {
public void method1(A x) {
System.out.println("C");
}
}
class D extends C {
public void method1(D x) {
System.out.println("D");
}
}
public class test {
public static void main(String[] args) {
C c = new D();
B b = c;
c.method1(c); // prints C
b.method1(b); // prints C
}
}
好的,这就是我的想法:c.method1(c) 调用 C 中的 method1 而不是 D 中的 method1,因为 c 被清除为 C,因此 D 中的 method1 不可见。但是 b.method1(b) 比较难。 B 没有 method1,我假设将使用父类(super class)中的 method1,但事实并非如此。为什么要使用C中的方法?我在 b 中放置了一个新的 D,但是 D 的特化是不可见的,因为 b 来自类型 B。
最佳答案
总而言之,这是每个继承级别上每个方法的可见性:
D 类:
public void method1(D x) { System.out.println("D"); }
public void method1(A x) { System.out.println("C"); }
public void method2() { System.out.println("B"); }
C 类:
public void method1(A x) { System.out.println("C"); }
public void method2() { System.out.println("B"); }
B 类:
public void method1(A x) { System.out.println("A"); }
public void method2() { System.out.println("B"); }
A 类:
public void method1(A x) { System.out.println("A"); }
同样重要的是要指出,您示例中的变量“c”和“b”是同一个对象,并且是 D
的实例。
所以...如果您调用 c.method1(c);
,它会打印“C”,因为 D 是 A 的一个实例(它实际上是一个 D,但它也是一个继承的 A ),因此您可以调用 method1(A)
,它对于 D 打印“C”。 (那是满嘴)。你会问为什么它不打印“D”?因为变量声明为C
,编译器只能链接到method1(A)
。
如果您调用 b.method1(b);
,它会打印“C”,因为您的变量 b
实际上是 D
的一个实例>,因为您将其创建为 new D()
。实际上c
和b
指向同一个类型D
的对象。
调用方法时,JVM 在这种情况下查看对象 D
的实际类型,而不是它声明为 B
的类型。
一个很好的内存方法是当你有类似的东西时
B b = new D()
等式的左边部分主要由编译器使用。请记住,method1(A)
和 method1(D)
是两种不同的方法(因为不完全相同的签名,不同的参数类型)。
JVM 在运行时使用等式的右边部分。它定义了该变量 b
在运行时的实际类型。
关于java - Java中的继承和重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32821479/