public class A {
int method(A a) { return 1; }
static int method(B b) { return 2 + b.method((A)b); }
}
public class B extends A {
final int method(A a) { return 4 + super.method(a); }
int method(C c) { return 8 + this.method((B)c); }
}
public class C extends B {
int method(C c) { return 16 + method((A)c); }
}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
b.method(b); //returns 7 (4 + 2 + 1)
b.method(c); //returns 15 (8 + 4 + 2 + 1)
}
}
每个类都在自己的文件中。
为什么第一个呼叫返回7?对我来说,它应该返回其他东西,因为调用了B.方法(A(,然后调用了A.(B(,然后应该调用B中的东西,而不是A.(A(为什么第二个呼叫返回15?
有两种有效的方法可以为b.method(b);
:调用
final int method(A a) { return 4 + super.method(a); }
static int method(B b) { return 2 + b.method((A)b); } // inherited from A
编译器选择了一个更具体的method(B)
。它是静态的并不重要。静态方法也可以在实例上调用。另请参阅:是通过对象调用静态方法吗;糟糕的形式"?为什么?
现在我们需要解决b.method((A)b);
。b
的编译时类型是A
,所以编译器只在A
中搜索。参数表达式的编译类型也是A
。唯一适用的方法是:
int method(A a) { return 1; }
在运行时,发现b
是B
的实例,因此调用B
中的重写方法:
final int method(A a) { return 4 + super.method(a); }
现在我们解决super.method(a);
。这里涉及的类型与b.method((A)b);
中的类型完全相同,但我们使用的是super
,因此在B
的超类中,即在A
中的实现被调用:
int method(A a) { return 1; }
对于b.method(c);
,参数的编译时类型是C
,因此我们有三种适用的方法:
final int method(A a) { return 4 + super.method(a); }
static int method(B b) { return 2 + b.method((A)b); } // inherited from A
int method(C c) { return 8 + this.method((B)c); }
再次,选择最具体的method(C)
。
然后我们求解CCD_ 19。这是以与b.method(b);
完全相同的方式解决的。编译时类型是相同的。参数的运行时类型是C
对象这一事实并不重要,因为所有C
重写都是method(C)
方法,我们在解析b.method(b);
时从未调用过该方法。
对于B,有效函数如下
final int method(A a) { return 4 + super.method(a); }
static int method(B b) { return 2 + b.method((A)b); }
int method(C c) { return 8 + this.method((B)c); }
- 来自类B的重写方法(A A(
- 同样在重载静态int方法(Bb(的原因中
请注意,静态方法也可以在实例上调用。
现在,当由于方法重载了多个参数而调用method
时,它会查找参数适用于哪个方法。
此b.method(b); //returns 7 (4 + 2 + 1)
的函数调用堆栈
是
- 从类B调用方法(B B(返回2+B方法((A(B(
- 在类B方法(A A(中调用返回4+super.method(A(//由于super,它不调用重写的方法(A A(,它调用原始方法
- 在类A中调用静态int方法(A A(返回1
1 + 4 + 2 -> 7
对于b.method(c)
- 调用类B int方法(C C(返回8+this.method((B(C(
- 调用类B方法静态int方法(Bb(返回2+B.method((A(B(
- 调用类B最终int方法(A A(返回4+super.method(A(;//调用未覆盖的方法(A A(,因为super关键字
- 调用类A int方法(A A(返回1
1 + 4 + 2 + 8 -> 15