将子级转换为父级 - 由于缺少方法而导致编译时错误 - 为什么?



下面是将子类强制转换为父类,然后调用方法的简短示例。

我希望foo方法在子类中调用,而不是在父类中调用。 但是,我收到一个编译错误,说父类没有此方法。

为什么Java关心父类是否具有它,如果我只在子类上调用它?

public static void main(String[] args)
{
A a = new A();
B b = new B();
b.foo(1, 2, 3); // Ok
((A) b).foo(1, 2); // Also ok. 
// Prints "In foo(int, int) method of class B"
((A) b).foo(1, 2, 3); // Will not compile
}

代码后面...

class A 
{
public int foo(int a, int b) 
{
System.out.println("In foo(int, int) method of class A");
return 1;
}
}
class B extends A 
{
public int foo(int a, int b) 
{
System.out.println("In foo(int, int) method of class B");
return 0;
}
public int foo(int a, int b, int c) 
{
System.out.println("In foo(int, int, int) method of class B");
return -1;
}
}
((A) b)

被视为A,尽管它foo(int, int)B的。

这意味着,因为((A) b)被称为A,所以你只能调用A拥有的方法。

A只有foo(int, int),所以不能叫foo(int, int, int)

((A) b).foo(1, 2);工作是因为 A 具有具有匹配签名的方法 foo,但它执行 B 的 foo 而不是,因为在运行时 jvm 可以理解它正在使用 B 的实例。这在其他方法中不可用。

((A) b).foo(1, 2, 3); 
//is equivalent to
A b1 = new B();
b1.foo(1, 2, 3);

Java 是静态类型的,据编译器所知,您正在尝试在类型 A 上调用不存在的方法并抱怨。编译器不知道运行时类型是什么。

((A) b).foo(1, 2, 3);

上面的代码可以可视化为:

A a = (A)b;
a.foo(1, 2, 3);

如您所见,此处的引用变量属于类型"A",所有方法名称解析都应基于类型"A"。 具有三个参数(重载方法(的 foo(...( 在 A 中不存在,因此它会抛出错误。

您面临的问题与方法重载的概念有关。

foo(int a, int b, int c)不是A中的方法。尽管您定义的所有方法都具有相同的名称,但它们被视为单独的方法,因为它们每个方法具有不同数量的参数。

当您尝试调用((A) b).foo(1, 2, 3)时,b被视为A的实例。Java 试图在A中找到一个名为foo的方法,其中包含三个参数,但找不到它,因为它不存在。

最新更新