下面是将子类强制转换为父类,然后调用方法的简短示例。
我希望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
的方法,其中包含三个参数,但找不到它,因为它不存在。