代码之家  ›  专栏  ›  技术社区  ›  Hearen

为什么静态块不能访问在它之后定义的静态变量

  •  1
  • Hearen  · 技术社区  · 6 年前

    我查过了 Forward References During Field Initialization the answer from @assylias ,但我仍然没有得到答案 为什么?

    访问它?

       class Parent {
            static {
                i = 2; // valid
                // can only assign new value to it instead of accessing it?
    //            System.out.println(i); // invalid - compile-error
            }
            static int i = 0;
            static {
                i = 3; // valid
            }
        }
    

    这是因为:值还没有初始化,所以我们只是显式禁止您使用它?或者有什么和安全有关的事我不知道?


    这不是一个关于

    类名 ?

    这个问题是关于为什么我们有这个设计?为了什么目的?

    1 回复  |  直到 6 年前
        1
  •  4
  •   Pavel Smirnov Kiriti    6 年前

    静态字段已初始化 根据订单 它们出现在代码中。

    i 你只要对编译器说:“嘿,伙计,当你开始初始化这个变量时,把它的值设置为…”。但你不能 使用 直到它被初始化,因为它根本不存在。

    更新:

    正如James Gosling、Bill Joy、Guy Steele和Gilad Bracha在《Java语言规范》一书中所说:

    这些限制旨在在编译时捕获循环或 否则初始化格式不正确。

    static {
                i = 2;
                j = i + 5; //should it be 7 or 15?
    }
    static int i = 10;
    static int j;
    

    j 变量是7还是15? 如果是7,那么我们已经初始化了 变量两次,这是不可能的,因为字段是静态的。如果是15,那是什么 i = 2; 什么意思?

    这段代码是不明确的,所以Java规范不允许这样做。

        2
  •  0
  •   Hearen    6 年前

    经过进一步的阅读,我认为帕维尔在这一点上不太准确 @Holger 在评论中指出。

    我们已经初始化了两次i变量,这是不可能的,因为该字段是静态的。

    作为 12.4.2. Detailed Initialization Procedure

    对于每个类或接口C,都有一个 唯一初始化锁LC

    两次 对于类初始值设定项本身是可以的,只要它只是 一旦

    但帕维尔提供的演示仍然站在它的立场,所以我基本上只是在这里重用它,但有不同的解释。

    static {
           i = 2;
           j = i + 5; 
           // no one knows whether "i" here initialized properly here
    }
    static int i = 10;
    static int j;
    

    但是当你使用 MyClass.i 直接在 j = MyClass.i + 5 ,编译器就会知道这样就可以了 8.3.3. Forward References During Field Initialization 具体有四个条件。

    具体来说,如果 全部的 正确:

    1. 出现类或接口C中类变量的声明 使用类变量后的文本;

    2. 用法很简单 在C的类变量初始值设定项中

    3. 用法不在作业的左侧;

    本文对此进行了详细的讨论 answer

    可预测的行为 添加这些限制。另一个官方目的在 8.3.3. 字段初始化期间转发引用 .

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

        3
  •  0
  •   Sumit    4 年前

    这同样适用于非静态构件。可以在实例初始值设定项块中为它们赋值,但不能在初始化之前使用它们。

    class Parent {
        {
            x = 3; // works fine
            // System.out.println(x); // gives compilation error.
    
        }
        int x = 0;
    
        public static void main(String[] args) {
    
        }
    }
    
    推荐文章