Java静态初始化块上的奇怪代码

时间:2013-01-21 07:24:00

标签: java static initializer jls

在浏览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; }
}

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

3 个答案:

答案 0 :(得分:8)

您可以分配给比其声明更早的值 - 您无法读取它。所以这也失败了:

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

然而这很好:

static { j = 5; }
static int j;

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

  • 用法不在作业的左侧。

(该部分的双重否定让我头疼,但我认为与之相关!)

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

答案 1 :(得分:1)

实际上,它是编译器的基础,

赋值语句从从右到左执行。

e.g。i=2;

表示2分配给i,2表示常量,因此无需声明

另一方面,如果我们写

i=j+2;

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

答案 2 :(得分:0)

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

你应该只在一个静态块中放置所有内容,j初始化和表达式来编译代码。此代码有效:

public class Z {

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

}

的Davide