10

我无法理解初始化发生的顺序。这是我假设的顺序:

*Once per 
    1. Static variable declaration
    2. Static block
*Once per object
    3. variable declaration
    4. initialization block
    5. constructor

但根据这段代码,我显然错了:

    class SomethingWrongWithMe
    {
        {
            b=0;         //no. no error here.
            int a = b;   //Error: Cannot reference a field before it is defined.
        }
        int b = 0;
    }

如果我这样做,错误会消失:

    class SomethingWrongWithMe
    {
        int b = 0;
        {
            b=0;
            int a = b;   //The error is gone.
        }
    }

我无法弄清楚为什么没有错误

    b=0;
4

3 回答 3

4

Java 语言规范(第 8.3.2.3 节)说您可以在表达式的左侧使用变量,即在声明之前分配给它,但不能在右侧使用它。

所有变量都被初始化为其默认值,然后显式初始化程序和匿名块按照它们在源文件中的顺序运行。最后调用构造函数。

静态只在第一次使用类时运行一次。

编译错误似乎是 Java 的规则,而不是在每种情况下都必然有意义的东西。

于 2012-03-12T10:51:26.310 回答
3

变量定义不是在“之前”块完成的。它们都按照定义的顺序同时完成

class SomethingWrongWithMe {
    {
        b = debug("block 1");
    }
    int b = debug("define");
    {
        b = debug("block 2");
    }
    private int debug(String str) {
        System.out.println(str);
        return 0;
    }
}

输出

block 1
define
block 2
于 2012-03-12T10:39:33.090 回答
1

首先,您的假设或多或少是正确的,除了声明(带有初始化,例如int b = 0)和实例初始化程序块按照它们编写的顺序执行。

int b = 0;   // executed first

{
    b = 1;   // executed second
}

int a = b;   // executed third

另请注意,声明ieint b执行。声明只是声明变量的存在。

至于你得到的错误(或者,你没有得到的错误),我同意它看起来很奇怪。我假设编译器处理在表达式中引用变量并以不同方式为其赋值。在实例初始化程序中写入变量时,它只检查变量是否存在,而从变量读取时,它要求在实例初始化程序块上方声明它。我会看看我是否可以在 JLS 中找到参考。

于 2012-03-12T10:34:16.867 回答