Ask*_*ker 6 java methods inheritance invoke
我正在攻读考试,我需要一些帮助才能理解以下剪辑代码中发生了什么.
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
}
}
Run Code Online (Sandbox Code Playgroud)
好吧,这就是我的想法:c.method1(c)在C中调用method1而在D中调用method1,因为c作为C是decleard,因此D中的method1不可见.但是b.method1(b)更难.B没有method1,我假设将使用超类中的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"); }
Run Code Online (Sandbox Code Playgroud)
C级:
public void method1(A x) { System.out.println("C"); }
public void method2() { System.out.println("B"); }
Run Code Online (Sandbox Code Playgroud)
B级:
public void method1(A x) { System.out.println("A"); }
public void method2() { System.out.println("B"); }
Run Code Online (Sandbox Code Playgroud)
A类:
public void method1(A x) { System.out.println("A"); }
Run Code Online (Sandbox Code Playgroud)
同样重要的是要指出示例中的变量'c'和'b'是同一个对象,并且是一个实例 D.
所以...如果你打电话c.method1(c);,它打印"C",因为D是A的实例(它实际上是D,但它也是A的继承),所以你可以调用method1(A),对于D,打印"C".(那是满嘴).为什么不打印"D"你会问?因为变量声明为a C,编译器只能链接到该变量method1(A).
如果你打电话b.method1(b);,它打印"C",因为你的变量b实际上是a的一个实例D,因为你创建它new D().实际上c并b指向同一类型的对象D.
调用方法时,JVM会查看D此例中对象的实际类型,而不是它所声明的内容B.
记住的一个好方法是当你有类似的东西时
B b = new D()
等式的左边部分主要由编译器使用.请记住,method1(A)并且method1(D)是两种不同的方法(因为不是完全相同的签名,不同的参数类型).
等式的右边部分由JVM在运行时使用.它定义了该变量在运行时的实际类型b.
让我们以示例代码为例并注释调用哪个方法、为什么调用它以及为什么这里不是所有内容都继承。
\n\nclass A {\n public void method1(A X) {\n System.out.println("A"); <--|\n } |\n} |\nclass B extends A { |\n public void method2() { | This is the only overriding happening\n System.out.println("B"); | because they share the signature method1(A)\n } | The other signatures are method1() from class B\n} | and method1(D) from class D\nclass C extends B { |\n public void method1(A x) { |\n System.out.println("C"); |\n } -------\n}\nclass D extends C {\n public void method1(D x) {\n System.out.println("D");\n }\n}\npublic class test {\n public static void main(String[] args) {\n C c = new D();\n B b = c;\n c.method1(c); // prints C\n b.method1(b); // prints C\n }\n} \nRun Code Online (Sandbox Code Playgroud)\n\n由于您正在从定义的对象调用 method1,因为C您正在获取结果 C。 \n尽管该类有方法,但该类已知的唯一方法 \xc2\xb4Object是 method1(A) 和 method1()。由于您的类被定义为 C,它将正确调用类中的方法C,因为类中的 method1 函数D不会覆盖类中的方法C。
编辑以回答您的评论:
\n\nmethod1(A)此时您正在调用带有签名的方法。由于您Object实际代表\xc2\xb4s 该类,D它会注意到该方法method1(A)被先前继承的类覆盖C,因此将打印C。用基本的话来说,类的定义定义了允许您调用哪些方法(在对象的可见范围内),但它所引用的对象的实际类型定义了如何调用该方法(如果它\xc2\ xb4s 在某些时候会被覆盖)。