我写下了这个迷你程序:
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 - 在构造函数之前初始化的变量..
编辑 - 我编辑了代码,因此不相关的代码不会混淆
答案 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。