2012-06-18 32 views
2

奇怪,但我找不到这个问题的重复。 我有一个超类overrideMe()方法和一个覆盖它的子类。 在调用子类构造函数之前,最终字段是否真正初始化? 正如我从输出中看到的那样。子类中的最终字段初始化

下面是输出: 超类构造 STR值:someValue中 子类构造 STR值:someValue中

可否请你给我讲解一下? 我认为实例变量是在构造函数调用中初始化的,但不是在它之前。

下面的代码:

public class Test { 
    public Test() { 
    System.out.println("Superclass constr"); 
    overrideMe(); 
    } 

    public void overrideMe() { 
    } 
} 

class Ext extends Test { 
    private final String str = "someValue"; 

    public Ext() { 
    System.out.println("Subclass constr"); 
    } 

    @Override 
    public void overrideMe() { 
    System.out.println("str value: " + str); 
    } 

    public static void main(String[] args) { 
    Ext test = new Ext(); 
    test.overrideMe(); 
    } 
} 

编辑: 如果我declasre STR场非最终,它在构造函数中调用子类返回null如我所料。

+0

每个构造函数都会先调用'super'(或'this'调用'super'),这样超类始终会被初始化。 (除了没有超类的'java.lang.Object') –

回答

2

是在构造函数被调用之前初始化字段,并且这个字段在超载之前从上层类开始。

这里是一个一般性介绍:http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ306_014.htm

+2

[JLS 7](http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.5)为更清楚 –

+0

糟糕,这是一个非常愚蠢的问题:) 我仍然不能得到的唯一的事情是为什么最终字段不初始化为null。 – iozee

+0

@iozee决赛场永远不会改变。它无法在null处初始化并在此之后更改值。 –

1

与初始化最后一个字段将与由编译器的常量字符串来代替,这就是为什么它似乎是超级构造函数返回即使前场被初始化。

如果最后一个字段是空白的inited,这意味着它是在子类的构造函数中插入的,那么超级构造函数当然会看到一个null。

如果该字段既不是最终的也不是静态的,并且提供了初始化程序,则它将在超级构造函数之后和子构造函数之前进行插入。