【问题标题】:Strange code on Java Static Initialization BlocksJava静态初始化块上的奇怪代码
【发布时间】:2013-01-04 05:42:04
【问题描述】:

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

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

【问题讨论】:

  • 它们是声明,在运行任何代码之前就知道......这就像问为什么我可以从要调用的方法上方定义的方法调用方法
  • @Esailija:i 和 j 有什么区别。为什么只针对j 出错?如果您提供更多信息会很好。

标签: java static initializer jls


【解决方案1】:

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

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

这很好:

static { j = 5; }
static int j;

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

  • 用法不在作业的左侧。

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

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

【讨论】:

  • 你的意思是 - you just *can't* read it,在你的第一个声明中。
【解决方案2】:

其实,它是一个编译器基础,

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

例如i=2;

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

另一方面,如果我们写

i=j+2;

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

【讨论】:

    【解决方案3】:

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

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

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

    大卫

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 2010-09-25
      • 2023-03-26
      • 2012-09-15
      • 1970-01-01
      相关资源
      最近更新 更多