0
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方法并输出父类的数据变量 。这不是正确答案,根据答案是子类的输出数据

谁能向我解释一下,我的推理有什么问题?

4

3 回答 3

4

这是由于多态性。您覆盖子中的print()方法,以便当子实例调用fun()它时,它使用该print()方法的子类版本。

由于实例是子类,它将使用它拥有的方法的版本,而不是它的父类。

可以在此处找到有关 JVM 如何解析其方法的好资源

于 2013-07-26T10:29:53.570 回答
1

现在关于 call2,因为 fun 只存在于父类中,所以调用会去那里,理想情况下应该调用父类的 fun 方法并输出父类的数据变量。这不是正确答案,根据答案是子类的输出数据。

这是不正确的。fun()ofBaseClass将调用print()of,Subclass因为它被覆盖了。运行时多态性适用于此。

于 2013-07-26T10:31:49.987 回答
1
   案例 1:obj.fun();

您已经覆盖了print();方法。
在运行时,java 根据对象类型解析方法调用。所以在这里它首先
搜索方法,它没有在那里找到方法, 因为你没有它(你没有在那里被覆盖), 然后它去(父)类并在那里找到方法。fun()SubClass
SubClassfun()
BaseClassfun()

然后有一个方法print()必须执行。
这里也跟这里一样,先在里面搜索,在 里面SubClass找到并执行print()
SubClass

这就是为什么你会得到这样的结果。

  案例2:System.out.println(obj.data)

这里data是变量,
编译器在解析对变量的访问时(以及在解析重载时)只考虑声明的变量类型。
这里声明的类型是BaseClass,所以结果是101

如果你创建这样的对象

   SubClass obj2 = new SubClass(); 
   System.out.println(obj2.data); 

然后结果将是。因为202声明的类型是“子类”。

于 2013-07-26T10:33:42.810 回答