Java中静态和非静态前向引用的内部工作

时间:2018-01-02 17:59:34

标签: java static non-static forward-reference

我正在使用Java中的前向引用,并想知道为什么Java允许使用ClassName(在静态变量中)或在实例变量的情况下使用this引用进行前向引用?在JVM级别发生的后台进程是什么?例如:

静态转发参考

class StaticForwardReferences {
    static {
        sf1 = 10;   // (1)
        int b = sf1 = 20;   // (2)
        int c = StaticForwardReferences.sf1; // (3) Works fine
        // Above statement allows the allocation of value of 'sf1'
        // to variable 'c' just because it is accessed with class name
        // instead of direct name

        // whereas below statement throws illegal forward reference
        // error at compile time
        System.out.println(sf1); // (4) Illegal forward reference
    }
    static int sf1 = sf2 = 30;
    static int sf2;

    public static void main(String[] args) {}
}

如果我们打印变量{{}的值,是否存在任何类型的临时存储,当我们通过在上面的(1)和(2)步骤中完成声明之前将变量分配给我们进行前向引用时存储值1}},它显示了最近一次分配对c所做的值。

非静态转发参考

sf1

请介绍上述两种情况后幕后发生的后台流程。提前致谢! :)

3 个答案:

答案 0 :(得分:2)

JLS, Section 8.3.3,说明了对静态变量(“类变量”)进行前向引用的条件是编译器错误,尽管它没有说明推理。

  

使用类变量,其声明在使用后以文本形式出现有时受到限制,即使这些类变量在范围内(第6.3节)。具体来说,如果满足以下所有条件,则为编译时错误:

     
      
  • 在使用类变量后,类或接口C中的类变量声明以文本形式出现;

  •   
  • 在C的类变量初始值设定项或C的静态初始化程序中使用简单名称;

  •   
  • 使用不在作业的左侧;

  •   
  • C是封闭使用的最里面的类或接口。

  •   

italic 强调我的)

实例变量转发参考错误出现时具有类似条件:

  

使用在使用后以声明方式显示声明的实例变量有时会受到限制,即使这些实例变量在范围内也是如此。具体来说,如果满足以下所有条件,则为编译时错误:

     
      
  • 在使用实例变量后,类或接口C中的实例变量声明以文本形式出现;

  •   
  • 在C的实例变量初始值设定项或C的实例初始化程序中使用简单名称;

  •   
  • 使用不在作业的左侧;

  •   
  • C是封闭使用的最里面的类或接口。

  •   

italic 强调我的)

在这两种情况下,使用简单名称是关键条件。这意味着使用不带任何限定符的变量,例如this或类名。这就是this.nsf1NonStaticForwardReferences中有效的原因。如果删除this,则会发生错误。这也是sf1出错并且StaticForwardReferences.sf1;没有错误的原因。

答案 1 :(得分:0)

Java要求字段的声明必须在任何初始化程序中使用之前发生 表达式,如果在初始化程序中的赋值的右侧使用该字段 表达。这实质上意味着字段的声明必须在之前发生 在初始化表达式中读取字段的值。

使用简单名称进行正向引用时,静态初始化程序块中的代码是 也受上文讨论的阅读前声明规则的约束。

在实例初始化表达式中,关键字" this"和"超级"可以用来 引用实例初始化程序块中的当前对象。

答案 2 :(得分:0)

禁止前向引用并不意味着在初始化时创建变量。 “后台进程”就是一次性分配类和对象,给出(静态)变量default values。 (也就是说“零”:它可能在实践中用callocmemset实现。)

前向引用规则为meant,以防止看到这些第一个值,尤其是对于final变量,这些变量应该只有一个值。但它们存在以捕获人为错误并且本身并不完美:仅对于常量变量,初始化发生so early默认值是不可观察的。明确指定this或类名是证明这种效果的最简单方法。