3

在浏览 JLS 8.3.2.3时,我无法理解以下代码。

class Z {
static { i = j + 2; }
static int i, j;
static { j = 4; }
}

代码导致错误Cannot reference a field before it is defined

但是如果我将代码更改为

class Z {
static { i = 2; }
static int i, j;
static { j = 4; }
}

代码正在编译。但在这两种情况下,变量定义都在初始化块之后。这背后的奥秘是什么?

4

3 回答 3

8

您可以在其声明之前分配一个值 - 您只是无法读取它。所以这也失败了:

static { System.out.println(j + 2); }
static int j;

虽然这很好:

static { j = 5; }
static int j;

第 8.3.2.3 节中无效使用的四个条件之一是:

  • 用法不在作业的左侧。

(那部分的双重否定让我头疼,但我认为这很相关!)

老实说,规范的那部分是我见过的最糟糕的部分之一——它真的不清楚。但结果是你可以分配但不能阅读:)

于 2013-01-21T07:32:09.437 回答
1

实际上,它是一个编译器基础知识,

赋值语句从右到左执行。

例如i=2;

这意味着 2 分配给 i,并且 2 是常数,因此无需声明它

另一方面,如果我们写

i=j+2;

它将首先编译 j 然后将其分配给 i 因此它会导致错误,因为 j 尚未定义。

于 2013-01-21T07:39:05.830 回答
0

i = j + 2;您使用j 在不同静态块中初始化的变量。

您应该将所有内容放在一个静态块中,将j初始化和表达式放在一起,以编译代码。此代码有效:

public class Z {

    static int i, j;
    static { j = 4; 
            i = j + 2; }

}

戴维德

于 2013-01-21T07:38:17.917 回答