构造函数何时初始化?

时间:2017-02-15 14:04:51

标签: java string inheritance constructor initialization

我写下了这个迷你程序:

A上课:

public class A
{

    public A()
    {
        System.out.println(getS());
    }

    public String getS() { return s;}


}

B上课:

public class B extends A
{
    private String s = "hello2";

    public String getS() { return s;}

}

main

public static void main(String[] args)
{
    B b = new B();
}

并打印出来:

null

为什么?
我知道打印的字符串是B&#39的字符串,但为什么它之前没有初始化?

根据this answer - 在构造函数之前初始化的变量..

编辑 - 我编辑了代码,因此不相关的代码不会混淆

3 个答案:

答案 0 :(得分:5)

以下是正在进行的:构建B时,构造函数需要做的第一件事就是构造A。这是在B自己的字段s初始化之前完成的。

A构建自己的s,然后调用getS。但是,它没有自己的getS,因为B为它提供了覆盖。回想一下,B.s尚未初始化。这就是您看到null打印的原因。

后续阅读:What's wrong with overridable method calls in constructors?

答案 1 :(得分:3)

发生了什么:

您创建了一个B实例,这将调用super()所以A的构造函数。

这里将使用getter getS()进行打印。这将使用B的getter,因为这是this的类型,但是在这个getter中,String还没有instanciate,因为它仍然在进行超类构造,所以它返回null。

请注意String s中的A隐藏B中的public class A{ static{System.out.println("sA");} {System.out.println("A1");} public Main() { System.out.println("new A"); } {System.out.println("A2");} public static void main(String[] args) { new A(); } } class B extends Main { static{System.out.println("sB");} { System.out.println("B1"); } public B() { System.out.println("new B"); } { System.out.println("B2"); } }

实例期间的订单是:

  • 静态(来自超级然后是类)
  • 超类声明(声明然后是构造函数)
  • 阻止声明
  • 构造函数

见:

sA
sB
A1
A2
new A
B1
B2
new B

输出:

$balance

答案 2 :(得分:1)

它打印null因为你在java中有多态性。你覆盖了方法getS()。因此,当您从A调用它时,您尝试从类B调用getS()。但是您还没有创建类B的实例,因为您需要首先完成类A.所以B类中的String尚未初始化,因为它会得到null。