我有这些课程:
class A {
public void f() { System.out.println("f() in A"); }
public void g() { System.out.println("g() in A"); f(); }
}
class B extends A {
public void f() { System.out.println("f() in B"); }
}
为什么
B b = new B();
A a = b;
a.g();
打印出来
g() in A
f() in B
而不是
g() in A
f() in A
我有什么遗失的吗?
答案 0 :(得分:3)
这是因为Java在类的方法上默认使用dynamic dispatch(并强制使用)。
此功能可确保在调用方法时,选择执行该方法的最专业版本。在您的情况下,从B extends A
开始,这意味着public void f()
的{{1}}实施比B
的实施更专业。因此,虽然A
静态类型为A a
,但它是A
类型的动态类型,并且选择了该方法。
答案 1 :(得分:2)
是的,即使变量" a"它是A类型,它拥有的对象引用是B类型,所以B中的f()是被调用的。
答案 2 :(得分:1)
https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
这称为多态性。它允许我们做一些事情,比如拿一个Animal类型的列表,但是当我们把一只猫放进去,然后做animal.performcall()它会打印一个喵喵。这是我老师多年前给我的例子,无论如何:)
答案 3 :(得分:0)
对象的引用变量类型确定可以访问哪些方法。
对象的类确定存在哪些方法。这些存在但无法访问的方法可以通过转换来访问。
即:((B) a).g();
允许您访问G的B
版本。这仅适用,因为a
下面是B
。
答案 4 :(得分:0)
现在你已经了解了多态性和覆盖。
由于您没有得到预期的输出,我建议通过方法阴影或隐藏来获得预期输出
如果你重新定义基类非静态&派生类中的非私有方法,称为覆盖。
在此示例中,A保存B的实例,因此从B而不是A调用f()
。
如果重新定义基类静态方法/变量是派生类,则称为隐藏或阴影。
在上面的示例中,只需添加为static
方法修改的g()
,您将获得所需的输出。现在g()
方法
class A {
public static int i=10;
public static void f() {
System.out.println("f() in A:i="+i);
}
public void g() { System.out.println("g() in A"); f(); }
}
class B extends A {
public static int i=20;
public static void f() {
System.out.println("f() in B:i"+i);
}
}
public class Test2 {
public static void main(String args[]){
B b = new B();
A a = b;
a.g();
}
}
输出:
g() in A
f() in A:i=10