这是另一个 SCJP 问题。下面的代码打印出 Alpha:fooBeta:fooBeta:barBeta:bar
,我不明白为什么第一个 foo 调用选择了 Alpha 的 foo 而不是 Beta 的。如果将 Alpha.foo 参数更改为 String 而不是 String...,则输出为 Beta:fooBeta:fooBeta:barBeta:bar
,这是有道理的。
我的理解是,当您说 Alpha a = new Beta();
时,编译器会检查 Alpha.foo,但 JVM 实际上会运行 Beta.foo。一方面,Beta 确实有一个 foo 方法,其签名与调用相匹配。另一方面,我认为可变参数方法仅在没有其他方法与调用匹配时才运行。所以这是我认为不应该运行 Alpha.foo 的两个原因。这种理解的哪一部分是错误的?
谢谢!
class Alpha {
public void foo(String... args) { //if this were String args, then it makes sense
System.out.print("Alpha:foo");
}
public void bar(String a) {
System.out.print("Alpha:bar");
} }
public class Beta extends Alpha {
public void foo(String a) {
System.out.print("Beta:foo");
}
public void bar(String a) {
System.out.print("Beta:bar");
}
public static void main(String[] arg) {
Alpha a = new Beta();
Beta b = (Beta) a;
a.foo("test");//confusing line
b.foo("test");
a.bar("test");
b.bar("test");
} }
编辑:我想我现在知道我在哪里误解了事情。我认为在 SuperClass sc = new SubClass();
情况下,运行时在 sc 上调用的任何方法都会在 SubClass 中搜索,尽管它们会在编译时在 SuperClass 中搜索。事实证明,正如我现在认为我理解的那样,无论在 sc 上调用什么方法,都将在 编译时和运行时在 SuperClass 中搜索,除非 SubClass 提供了“更好”的版本的方法。然后,即使在编译时,编译器也会知道要调用的方法是子类版本。
最佳答案
带有 String[]
或 String...
参数的方法和带有 String
参数的方法不共享相同的签名.字符串数组是一个完全独立的类型,因此它是一个标准的重载并且没有发生多态性。编译器认为它是类型“Alpha”的实例,并调用在那里找到的 foo
方法。 Beta 中的 foo
方法没有被调用,因为它实际上并不是 Alpha 版本的覆盖。
(这是 @Override
注释派上用场的地方。如果您尝试在 foo
的 Beta 版本上使用它,您会遇到编译器错误。 )
关于java - 在此代码中如何选择一种方法而不是另一种方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3795026/