5

考虑以下场景:
代码:1

public class StaticDemo {
    static{
        b=5;
        System.out.println("Static B:"+b);/*Compilation error:"Cannot reference a field before it is defined"*/
    }
    static int b;
    static{
        System.out.println("B:"+b);
    }
    public static void main(String[] args) {    
    }
}

将代码注释如下,没有错误,并且显示了以下输出。
代码:2

public class StaticDemo {
    static{
        b=5;
        //System.out.println("Static B:"+b);
    }
    static int b;
    static{
        System.out.println("B:"+b);
    }
    public static void main(String[] args) {    
    }
}

输出-

B:5

如果执行基于静态变量或块的写入顺序。

  1. 为什么初始化( )没有抛出编译错误b=5,如代码:2所示。

  2. 如果 Code:2 为真,请解释为什么 Code:1 会抛出错误?

4

3 回答 3

3

来自Java 语言规范 §8.3.2.3

仅当成员是类或接口 C 的实例(分别为静态)字段并且满足以下所有条件时,成员的声明才需要在使用之前以文本形式出现:

  • 该用法发生在 C 的实例(分别为静态)变量初始化器或 C 的实例(分别为静态)初始化器中。
  • 用法不在作业的左侧。
  • 用法是通过一个简单的名称。
  • C 是包含用法的最里面的类或接口。

如果不满足上述四个要求中的任何一个,则为编译时错误。

[...]

上述限制旨在在编译时捕获循环或其他格式错误的初始化

换句话说,可以写入稍后在类中声明的字段,但不能从中读取

在我引用的部分之后的示例框中有更详细的示例。

于 2014-03-25T11:55:54.333 回答
2

在第一个示例中,变量b由第一个静态块初始化,这是第一个要执行的静态块。编译器不记得第一行,因此在静态块的第二行中,它抱怨引用b,因为 'b' 可能尚未初始化。

当编译器通过了 的定义时b,他肯定b被初始化了。因此,您的代码可以引用/访问它。

在源代码中发生之前初始化静态变量是可以的,但只有在它发生之后才允许访问它。

如果您查阅Java 规范,它会说明以下内容:

Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class. 

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
    1) A static field declared by T is assigned.
    2) A static field declared by T is used and the field is not a constant variable (§4.12.4).

1) 说,在直接分配静态字段之前执行静态初始化程序。2)说,在你可以使用一个字段之前,初始化程序(块和字段初始化程序)必须已经执行。

因此,您可以为静态初始化程序块中的静态字段分配值,但在所有初始化完成之前不能使用它。我就是这么理解的。

于 2014-03-25T11:44:36.690 回答
-1

执行顺序是从上到下。您不能在声明之前使用静态字段。

如果 Code:2 为真,为什么 Code:1 会抛出错误

您试图在声明变量之前使用它。BTW not error 在运行时抛出。这是一个编译器错误。

于 2014-03-25T11:41:01.727 回答