4

这是一段 Java 代码:

static {        
    ture = 9;       
}
static int ture;
{ // instance block 
    System.out.println(":"+ture+":");           
}

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

现在为什么实例块中的值 9 被打印了 3 次?顺便说一句,该类的实例已经创建了 3 次。那不是家庭作业,我正在学习 Java 以获得认证。

4

3 回答 3

11

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

您引用的代码中没有足够的信息来回答您的第二个问题。(无论如何,在 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:了 3 次,那么您似乎正在使用未显示的代码创建三个实例。

于 2012-12-02T16:35:35.063 回答
2

静态初始化程序按照它们出现的顺序执行,而声明根本不执行,这就是它们的名字。这就是为什么您的代码可以毫无问题地编译的原因:类结构是在编译时从声明中组装而成的,而静态块是在运行时执行的,在处理完所有声明之后很久。

于 2012-12-02T16:54:37.597 回答
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

您的示例是允许的,因为该字段的使用位于作业的左侧。显然语言设计者并不认为这太令人困惑。尽管如此,如果可以的话,我们可能应该始终避免前向引用。

于 2012-12-02T18:43:45.173 回答