【问题标题】:How the order of execution is performed between static variables and blocks?静态变量和块之间的执行顺序是如何执行的?
【发布时间】:2014-05-03 05:20:27
【问题描述】:

考虑以下场景:
代码:1

public class StaticDemo {
    static{
        b=5;
        System.out.println("Static B:"+b);/*Compilation error:"Cannot reference a field before it is defined"*/
    }
    static int b;
    static{
        System.out.println("B:"+b);
    }
    public static void main(String[] args) {    
    }
}

注释如下代码,没有错误,并显示以下输出。
代码:2

public class StaticDemo {
    static{
        b=5;
        //System.out.println("Static B:"+b);
    }
    static int b;
    static{
        System.out.println("B:"+b);
    }
    public static void main(String[] args) {    
    }
}

输出-

B:5

如果执行是基于静态变量或块的写入顺序。

  1. 为什么初始化时不抛出编译错误 (b=5) 如代码:2所示。

  2. 另外请解释为什么 Code:1 会抛出错误,如果 代码:2 是真的吗?

【问题讨论】:

标签: java static scope static-variables static-block


【解决方案1】:

来自Java Language Specification §8.3.2.3

仅当成员是类或接口 C 的实例(分别为静态)字段并且满足以下所有条件时,成员的声明才需要在使用之前以文本形式出现:

  • 在 C 的实例(分别为静态)变量初始化器或 C 的实例(分别为静态)初始化器中使用。
  • 用法不在作业的左侧。
  • 用法是通过一个简单的名称。
  • C 是包含用法的最内层类或接口。

如果上述四个要求中的任何一个不满足,则为编译时错误。

[...]

上述限制旨在在编译时捕获循环或其他格式错误的初始化

换句话说,可以写入到稍后在类中声明的字段,但不能读取

在我引用的部分之后的示例框中有更详细的示例。

【讨论】:

  • +1:打败我。只花了十分钟寻找规范的链接>.
  • @ian-roberts 非常感谢。
  • @Vasanth - 如果您发现有帮助的答案,也不要忘记给它投票。 :)
  • @Vasanth - 没问题。
【解决方案2】:

在第一个示例中,变量b 被第一个静态块初始化,这是第一个要执行的静态块。编译器不记得第一行,因此在静态块的第二行中,它抱怨引用 b,因为 'b' 可能尚未初始化。

当编译器通过b的定义时,他确定b被初始化了。因此,您的代码可以引用/访问它。

在源代码中在静态变量发生之前初始化它是可以的,但只有在它发生之后才允许访问它。

如果您咨询Java Specification,它会说明以下内容:

Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class. 

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
    1) A static field declared by T is assigned.
    2) A static field declared by T is used and the field is not a constant variable (§4.12.4).

1) 说,在直接分配静态字段之前执行静态初始化程序。 2) 说,在你可以使用一个字段之前,初始化程序(块和字段初始化程序)必须已经执行。

因此,您可以为静态初始化程序块中的静态字段分配值,但在所有初始化完成之前不能使用它。我就是这么理解的。

【讨论】:

  • 在源代码中发生静态变量之前初始化它是可以的,但只有在它发生之后才允许访问它。我能够得到你想要的说。但是,您能否提供任何链接或资源来解释这种情况。这真的很有帮助。
【解决方案3】:

执行顺序是从上到下。在声明之前不能使用静态字段。

如果 Code:2 为真,为什么 Code:1 会抛出错误

您试图在声明之前使用变量。 BTW not error 在运行时抛出。这是编译器错误。

【讨论】:

  • 如果代码是自下而上的,怎么给尚未声明的变量赋值呢?
  • 没错。必须承认我不知道这是可能的。 “代码 2”确实可以编译,而“代码 1”没有。
  • 已声明,类变量在静态块运行前被识别。
  • @RudiKershaw 请在您使用的条款中更加准确。 'recognized' 不能解释事情 - 在代码 1 中,bb = 5 中是“recognized”,但在 print 语句中没有。
  • @ErwinBolwidt - 我的意思是 b 已经被声明,因为静态块在声明之后运行。编译错误是因为非法转发异常(“在初始化期间使用静态非最终变量”)。
猜你喜欢
  • 2022-12-22
  • 1970-01-01
  • 1970-01-01
  • 2015-09-05
  • 1970-01-01
  • 2023-01-17
  • 2017-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多