Java 多态实例如何选择其方法?
我无法理解这段代码的行为。 a被定义为a,c被定义为c。 然后,在公共类的末尾,a=c。 当a调用display()方法时,它会到达它的C版本。 但是当a调用f()时,它只到达a版本,尽管第一个参数(byte和long)比float更符合long 这是一本书中的练习,但解释很少,或者根本不存在Java 多态实例如何选择其方法?,java,polymorphism,overriding,overloading,Java,Polymorphism,Overriding,Overloading,我无法理解这段代码的行为。 a被定义为a,c被定义为c。 然后,在公共类的末尾,a=c。 当a调用display()方法时,它会到达它的C版本。 但是当a调用f()时,它只到达a版本,尽管第一个参数(byte和long)比float更符合long 这是一本书中的练习,但解释很少,或者根本不存在 A类{ 公共空间显示(){ System.out.println(“我是A”); } 公共空间f(双x){ System.out.println(“A.f(double=“+x+”)); } } C类扩展
A类{
公共空间显示(){
System.out.println(“我是A”);
}
公共空间f(双x){
System.out.println(“A.f(double=“+x+”));
}
}
C类扩展了{
公共空间显示(){
System.out.println(“我是C”);}
公共空间f(长q){
System.out.println(“C.f(long=“+q+”));}
}
公共级多管炮{
公共静态void main(字符串参数[]){
字节bb=1;长q=4;浮点x=5.f;
System.out.println(“**A**”);
A=新的A();A.显示();
a、 f(bb);a.f(x);
System.out.println();
System.out.println(“**C**”);
C=新的C();C.显示();
c、 f(bb);c.f(q);c.f(x);
System.out.println();
a=c;a.显示();
a、 f(bb);a.f(q);a.f(x);
}
}
当调用a.f(bb)
或a.f(q)
或a.f(x)
时,编译器可以选择的唯一方法签名是类a
中定义的签名(或a
的任何超类),因为a
是a
类型的参考变量
因此,仅考虑公共无效f(双x)
。为了使public void f(long q)
成为重载解析的候选,您必须在调用f()
之前将a
转换为键入C
,因为只有类C
定义了具有该签名的方法
需要理解的重要一点是,方法重载解析发生在编译时。只有为其调用方法的引用变量的编译时类型才能确定哪些方法签名是方法重载解析的候选项,以及将选择哪个候选项。编译器选择的方法取决于声明的类型,而不是运行时类型。
声明为变量
A
的第一个系列只能调用一个方法(无论实例化为A
的运行时类型仅派生对象
):
对于第二个系列,由于C
是a
,因此编译器可以在此处绑定与调用匹配的最特定参数的方法,因此编译器可以绑定这些方法中的任何公共方法:
C c = new C();
c.f(bb); c.f(q); c.f(x);
但在最后一段可能会问你自己的代码中,a
将C
称为运行时对象,而将a
称为声明类型:
A a = new A();
// ...
a = c;
a.f(bb); a.f(q); a.f(x);
因此,只能调用
A
中定义的方法 我会尽量澄清一下@eran的答案,这样你就可以理解它了
一个子类拥有它的超类的所有方法,也许还有更多的方法。您有一个a
类型的变量,其中存储了C
类型的对象C
包含类A
中定义的所有方法,还有一个附加方法,即f(长q)
A
不知道这个新方法,因此由于将对象存储在变量A
中,因此不能调用f(长q)
但是,您可以调用
display()
,因为它是在A
中定义的,但它仍然是执行它的C
对象。我刚刚在另一个论坛上发现:
重载:(相同的函数名但不同的签名)
清楚且与本主题高度相关。您本可以提供一个更好的示例,删除所有不必要的代码以使其最小化(请参阅),但这仍然是一个有趣的问题。我不知道答案,但我担心这将是一个重复的问题。所以换句话说,发生这种情况是因为
display()
在编译时是可确定的,而f()
不是吗?@Gendarmedisplay()
和f(双x)
在编译时都是可确定的(当方法调用是针对类型a的变量时)。但是,在display()的情况下
,方法重写在运行时起作用-因为C有一个具有相同签名的display
方法,如果a
引用类C
,则执行C
的display
方法,而不是a
的方法“编译器可以选择的唯一方法签名是在类A(或A的任何超类)中定义的方法签名”为什么它在C中调用display?因为C
覆盖display()
,而它只重载f()
,@Tchae.@Gendarme,那么A只能
A a = new A();
// ...
a = c;
a.f(bb); a.f(q); a.f(x);