为什么打印静态变量值会在静态块中产生错误,而分配它时则不会

时间:2017-05-02 10:32:57

标签: java static-initialization static-block

public class ABC {


    static {       
       System.out.println(i);
    }

    static int i=10;

    static {
        System.out.println(i);
    }

    public static void main(String[] args)
    {
        System.out.println(3);

        ABC a = new ABC();
    }
}

给出错误;

can not reference a field before it is defined

但是跟着 -

public class ABC {
    static {       
        i=20;
        System.out.println(ABC.i); 
        System.out.println(i); //same error as above
    }

    static int i=10;

    static {
        System.out.println(i);
    }

    public static void main(String[] args)
    {

        System.out.println(3);

        ABC a = new ABC();
    }
}

不会抛出任何错误并编译并运行正常。即使我使用,

package com.sample.package2;

public class ABC {

    static {  
        System.out.println(ABC.i);
    }

    static int i=10;

    static {
        System.out.println("yahan 10" + i);
    }

    public static void main(String[] args)
    {
        System.out.println(3);

        ABC a = new ABC();
    }
}

运行正常。很困惑为什么会出现这个错误。有类似的问题,这听起来可能与你们中的一些人重复,但还没有找到明确的答案。初始化的顺序是什么。我相信静态块先于其他任何东西执行。如果我转移static int i=10;错误就会消失。静态变量在静态块之前初始化吗?

2 个答案:

答案 0 :(得分:0)

你所使用的被称为" 静态初始化块"。如果您已阅读the documentation of initializing fields,您将遇到以下内容(强调我的)

  

一个类可以有任意数量的静态初始化块,它们可以出现在类体中的任何位置。 运行时系统保证在源代码中按照它们出现的顺序调用静态初始化块。

在您的代码中,您在尝试调用它之后声明并初始化了i 。如果您在静态初始化之前完成了,则不会定义变量i

static {       
   System.out.println(i); // <-- where is i ?
}

static int i=10;

在定义类中的ABC.i之前使用i是有效的,因为当您调用ABC时,正在初始化类ABC。您必须查看初始化发生的时间。如果您选中JLS 12.4.1,则会注意到

  

类或接口类型T将在第一次出现以下任何一个之前立即初始化:

     

...省略...

     

使用T声明的静态字段,该字段不是常量变量

     

...省略...

表示ABC正在初始化。但是,在初始化期间,static { ... }方法再次被 调用,因为它使用了一次。在这里,不会抛出错误。因此,可以在ABC.i方法中调用static { ... }时检索指定的值,即使在该方法之后已定义i

答案 1 :(得分:-1)

static {       
   System.out.println(i);
}

static int i=10;

您之前正在初始化变量但之前调用它。因此它会抛出错误  wheras

static {       
    i=20;
    System.out.println(i);
}

  static {  
    System.out.println(ABC.i);
}

static int i=10;

首先初始化然后调用它。