什么时候是在java中创建的对象

时间:2018-05-17 04:51:44

标签: java method-overriding

鉴于以下代码段:

class SuperClass {
    SuperClass () {
        foo();
    }

    public void foo() {
        System.out.println("In SuperClass foo");
    }
}

public class SubClass extends SuperClass {
    private String str;
    SubClass() {
        str = "SubClass";
    }

    public void foo () {
        System.out.println("In SubClass foo value " + str.toLowerCase());
    }

    public static void main(String[] args) {
        SuperClass ref = new SubClass();
        ref.foo();
    }
}

此代码抛出NPE,因为在调用foo()时,它在SuperClass构造函数中实际调用SubClass foo()并抛出NPE。我想知道究竟什么时候在这里创建了SubClass对象,因为我们仍然在构造函数中初始化SubClass的成员变量,那么为什么在这里发生了重写?

3 个答案:

答案 0 :(得分:0)

作为链接:https://www.geeksforgeeks.org/g-fact-67/

在Java中,在派生类构造函数中自动调用没有参数的基类构造函数。


创建ref时,它有地址:SubClass @ c2e1f26。它是SubClass。 所以。当在SuperClass()构造中调用foo时,它会搜索SubClass中的foo()并执行它。

更新关注问题
  - 我们应该记住.SuperClass()构造函数是调用第一个SubClass()构造函数。所以当属性str没有初始化时。

答案 1 :(得分:0)

it will first call the subclass constructor then subclass to the superclass and then superclass to the object and the execution returns to the superclass then it will start printing.
the first statement will print
  

在SuperClass foo

     

在SubClass foo值子类

but since the str is not followed up then it will obviously throw the null pointer exception.

答案 2 :(得分:0)

初始化Subclass时,首先调用Superclass构造函数。需要在子类之前构造超类(更一般)(更具体)。有道理,对吧?

现在,在超类的构造函数中,调用了foo。猜猜哪个 foo被调用?子类的foo!这是因为您正在创建一个Subclass对象,因此您调用的每个实例方法都将调用子类的实现,因为polymorphism

因此调用了子类的foo并尝试打印str.toLowerCase()。请注意,由于尚未调用子类的构造函数,因此str未初始化,因此初始值为nil,抛出NullPointerException

如果子类的foo方法成功运行,那么超类的构造函数将返回,并且子类的构造函数最终将被调用。

当天的教训:不要在非final类的构造函数中调用非final方法。