静态块初始化

4
这是一段Java代码示例:
static {        
    ture = 9;       
}
static int ture;
{ // instance block 
    System.out.println(":"+ture+":");           
}

它是如何编译的?变量“ture”的声明在初始化之后进行。据我所知,静态块和字段按照它们出现的顺序执行。

现在为什么实例块内的值9被打印了3次?顺便说一下,该类的实例已创建3次。 这不是作业,我正在为认证学习Java。


你引用的代码中没有足够的信息来回答你的第二个问题。无论如何,在SO上,最好每个问题只问一个问题。 - T.J. Crowder
我真的不知道还能加什么来使第二个问题更完整。除了上面的代码之外,只有一个主方法。 - uml
@uml:您可以添加完整的类定义(例如,我的答案中的定义),并展示如何实例化它,因为如果您从未创建任何实例,则实例初始化程序根本不会运行。 - T.J. Crowder
3个回答

11

关于您的第一个问题,静态块确实按照它们出现的顺序进行处理,但是声明会在静态块之前先被处理。声明作为类的准备的一部分而被处理 (JLS §12.3.2),这发生在初始化之前(JLS §12.4.2)。为了学习目的,整个 JLS §12 可能有用,以及 JLS §8,特别是 §8.6JLS §8.7(感谢 Ted Hoppirreputable 提供相关章节。)

你引用的代码中没有足够的信息来回答你的第二个问题。(在SO上,每个问题最好只问一个问题。) 但是例如:

public class Foo {
    static {     
        ture = 9;   
    }

    static int ture;

    {   // instance block   
        System.out.println(":"+ture+":");

    }

    public static final void main(String[] args) {
        new Foo();
    }
}

只输出一次:9:,因为只创建了一个实例。如果删除new Foo();行,则根本不会输出。如果您看到:9:三次,则似乎在未显示的代码中创建了三个实例。


你可能想要添加一个指针到JLS的特定部分,以使其真正充实 ;) - Victor Sorokin
好的,我明白了。3个实例。我有很多垃圾代码,没有注意到我在主方法中一直在创建3个实例。 - uml
@uml:不错的交易 - 这就是为什么实例初始化程序会运行三次,因为每次创建实例时都会运行它。祝你在认证考试中好运! - T.J. Crowder
1
@VictorSorokin - 由于T.J.没有包含链接,这里是想要它们的人的链接。实例初始化程序在Java语言规范的§8.6中描述,静态初始化程序在JLS §8.7中描述。 - Ted Hopp
1
@TedHopp:我真正想找到的是一些说明你、我、Victor和Marko都知道的内容:声明发生在初始化程序运行之前,作为设置类的基本过程的一部分。那些链接很好,但它们没有说到这一点。这是如此隐晦,以至于我在愿意投入的时间内没有找到太多有用的信息。 :-) - T.J. Crowder
@T.J.Crowder 4.12.5,12.3.2,17.4.4 - irreputable

2

正如其他人所说,声明的位置通常并不重要。

但有时可能会引起混淆:

class Z {
    static int i = j + 2;  // what should be the value of j here?
    static int j = 4;
}

Java对前向引用进行了一些限制: http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.2.3 您的示例是允许的,因为该字段的使用在赋值的左侧。显然,语言设计师认为这并不太令人困惑。尽管如此,我们应该尽可能避免前向引用。

2
静态初始化器按照出现的顺序执行,而声明根本没有被执行,这就是它们得名的原因。这就是为什么您的代码编译时没有问题:类结构在编译时从声明中组装,静态块在运行时执行,在所有声明都被处理之后很长一段时间才会执行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接