class BaseClass {
int data = 101;
public void print() {
System.out.print(data + " ");
}
public void fun() {
print();
}
}
class SubClass extends BaseClass {
int data = 202;
public void print() {
System.out.print(data + " ");
}
}
class TestClass {
public static void main(String[] args) {
BaseClass obj = new SubClass();
obj.print();//call 1
obj.fun();// call 2
System.out.print(obj.data);//call2
}
}
所以我有一个父/子关系类和一个有call1,call2,call3的测试类。
1:关于call1,我的理由是,因为 print()被子类重写,函数调用将打印正确的数据变量。这似乎是正确的,因为这是正确的答案。
2:现在关于call2,因为fun只存在于父类中,所以调用会去那里,理想情况下应该调用父类的 fun 方法并输出数据父类的变量。根据子类的输出数据的答案,这不是正确的答案。
任何人都可以向我解释一下,我的推理有什么问题吗?
答案 0 :(得分:4)
这是由于polymorphism。您覆盖子项中的print()
方法,以便在子项调用fun()
实例时使用print()
方法的SubClass版本调用它。
由于实例是SubClass,它将使用它拥有的方法的版本而不是它的父版本。
可以找到有关JVM如何解析其方法的良好资源here
答案 1 :(得分:1)
现在关于call2,因为fun只存在于父类中,所以 电话将去那里,理想情况下应该调用有趣的方法 父类并输出父类的数据变量。这是 不正确答案,根据答案输出数据 孩子班。
这不正确。 fun()
的{{1}}会调用BaseClass
的{{1}},因为它会被覆盖。 运行时多态性适用于此处。
答案 2 :(得分:1)
case 1 : obj.fun();
您已覆盖print();
方法
在运行时,java根据对象类型解析方法调用。
所以在这里它首先在fun()
中搜索方法SubClass
,但是没有在那里找到方法,
因为你SubClass
没有它(你没有被fun()
覆盖),而且
然后它转到BaseClass
(父)类并找到fun()
方法。
然后有一个必须执行的方法print()
此处也遵循相同的步骤,首先在SubClass
中搜索并找到print()
在SubClass
本身并执行它。
所以这就是你得到的结果。
case 2 : System.out.println(obj.data)
此处data
是变量,
编译器在解析对变量的访问时(以及在解决重载时)仅考虑声明的变量类型
此处声明的类型为BaseClass
,因此结果为101
。
如果您创建这样的对象
SubClass obj2 = new SubClass();
System.out.println(obj2.data);
然后结果将是202
。因为声明的类型是'SubClass'。