如何知道在Java上的extends中执行的方法?
这是我的A班<;-B<;-C
class A {
void f ( A a ) { System . out . println ( " AA " );}
void f ( C c ) { System . out . println ( " AC " );}
}
class B extends A {
void f ( B b ) { System . out . println ( " BB " );}
}
class C extends B {
void f ( A a ) { System . out . println ( " CA " );}
void f ( C c ) { System . out . println ( " CC " );}
}
当我用流动代码实现main时,我不理解结果
public class app {
public static void main ( String [] args ) {
A aa = new A ();
B bb = new B ();
A ac = new C ();
A ab = new B ();
B bc = new C ();
C cc = new C ();
aa.f ( ac );
bb.f ( ac );
ab.f ( bb );
bb.f ( ac );
bb.f ( cc );
}
}
结果是
AA
AA
AA
AA
CA //Edit : AC instead of CA
我不明白Java是如何找到这些结果的
请问有人能解释一下结果吗
# 1 楼答案
方法概述
让我们一步一步来看看你的例子。您有三个类,如果我们列出它们的所有方法(包括重载和继承的方法),那么您有:因此
B
类定义了一个新的重载的变量,它接受B
。C
类继承了A
和B
的所有内容,覆盖了A
的两个方法解释
现在开始测试:
您的命名约定意味着实际实例是右字符类型,而您通过左字符类型的变量引用它。因此
ab
实际上是类B
的一个实例,并由允许引用A
类型的变量引用知道了这一点,就很容易理解结果。第一个例子:
我们有一个类型为}和{}中选择{},因为{}位于{}类型的变量中,而不是{}。由于使用了
A
的实例,在类型为A
的变量中。参数的类型为C
,变量的类型为A
。非常重要的是,请注意变量的类型将用于确定要选择的重载。因此,Java从{#1
,因此输出为"AA"
接下来的三次通话也会发生同样的情况,尽管第三次通话也很有趣:
虽然
ab
实际上是一个B
实例,因此它有一个void f(B b)
(#5
)打印"BB"
,但我们看到"AA"
。这是因为ab
再次位于类型为A
的变量中。因此,编译器将查看A
提供的方法。唯一适用的方法是f(A a)
(#1
),因为ab
肯定不是C
。因此它再次使用#1
并打印"AA"
最后一个例子中的打字错误
你的最后一个例子有点不对劲。我猜您输入错了,因为代码将输出
"AC"
,而不是"CA"
:原因很简单
bb
是B
类型,也是它的变量。因此,我们可以从B
的方法中进行选择(以及从A
继承的方法)。参数的类型为C
,其变量的类型相同。所以我们调用方法#4
,printing"AC"
类型概述
以下是最终相关的实际类型情况:
JLS定义
Java如何确定调用哪些方法的规则在Java语言规范中有明确定义。如果你感兴趣的话,你可以读它。相关章节为15.12 Method Invocation Expressions。特别是{a2}和{a3}。部分摘录: