我们第一次使用类时是否总是执行静态代码?

时间:2010-07-07 15:02:14

标签: java static jvm final

我们的应用程序正在使用依赖于执行静态代码的顺序的初始化代码,我想知道这个顺序是否在所有JVM中都是一致的。

以下是我的意思的样本:


public class Main {

    static String staticVar = "init_value";

    public static void main(String[] args) {

        System.out.println(A.staticVar);
        staticVar = "mainValue";
        System.out.println(A.staticVar);
    }
}

public class A {
    static String staticVar = Main.staticVar;
}

会给:

init_value
init_value


public class Main {

    static String staticVar = "init_value";

    public static void main(String[] args) {

        // System.out.println(A.staticVar);
        staticVar = "mainValue";
        System.out.println(A.staticVar);
    }
}

public class A {
    static String staticVar = Main.staticVar;
}

将给予(在我的环境中):

mainValue

总结一下,在所有JVM中,当我们第一次使用类时,是否总是执行静态代码?

8 个答案:

答案 0 :(得分:18)

编辑:尽管下面有所有的保证,如果你正在考虑依赖这类事情,我会尽力重构你的代码,以免它出现。虽然 保证可以正常工作,但它也可能使您的代码非常脆弱。静态初始化程序被称为“不可见”的事实使得它们相对难以推理和调试。


是的,这是由语言规范保证的。来自规范的section 8.7

  

在类初始化时执行在类中声明的任何静态初始值设定项,并且与类变量的任何字段初始值设定项(第8.3.2节)一起,可用于初始化类的类变量(第12.4节)。

     

StaticInitializer:static 阻止

     

静态初始化程序能够通过检查异常(第11.2节)突然完成(第14.1节,第15.6节)是编译时错误。如果静态初始化程序无法正常完成,则为编译时错误(§14.21)。

     

静态初始值设定项和类变量初始值设定项以文本顺序执行。

来自section 12.4

  

一个类的初始化包括   执行静态初始化程序和   静态字段的初始值设定项   在课堂上宣布。初始化   接口包括执行   声明的字段的初始值设定项   在界面中。

     

上课之前   初始化,它的直接超类   必须初始化,但接口   由班级实施不必   初始化。同样,   接口需要的超接口   不要在之前初始化   接口已初始化。

     

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

     
      
  • T是一个类,T的实例是   创建。
  •   
  • T是一个类和一个静态   调用T声明的方法。
  •   
  • 甲   T声明的静态字段是   分配
  •   
  • T声明的静态字段   使用,字段不是   常数变量(§4.12.4)。
  •   
  • T是一个   顶级类和断言   声明(§14.10)词汇嵌套
  •   

答案 1 :(得分:4)

第一次使用类时,始终会执行静态初始化程序(例如,staticVar声明)。

静态方法仅在调用时执行。在您的情况下,这发生了,因为静态void main(String [] args)是应用程序的入口点。但是如果你定义了一个不同的静态方法,那么就不会调用它。

也可以创建一个静态初始化块,在初次使用类之前也会自动调用它,例如

static {
  // some initialisation code here
}

答案 2 :(得分:3)

在所有平台上应该都是一样的。请参阅JVM规范:http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#19075

答案 3 :(得分:2)

Java规范的引用:

  

的初始化包含   执行静态初始化程序和   静态字段的初始值设定项   在课堂上宣布。初始化   接口包括执行   声明的字段的初始值设定项   在界面中。

答案 4 :(得分:1)

是的,根据Java Language Specification静态代码总是在所有(兼容的)JVM上以相同的顺序执行。

8.7 Static Initializers

  

静态初始值设定项和类变量初始值设定项以文本顺序执行。

答案 5 :(得分:1)

Dittos对其他海报,但让我补充说,依赖于你的例子中其他类的状态的静态初始化程序在我看来是非常脆弱和难以维护的代码。我将使用静态初始化器来填充内部类数据 - 用默认值或类似的东西填充数组。但我不认为我曾经看过另一堂课的数据。技术上合法,也许有一些奇怪的情况,这是一个好主意,但是很糟糕。

答案 6 :(得分:0)

是的,我相信根据定义,这将是重点。

答案 7 :(得分:0)

静态块将始终首先运行,而不仅仅是第一次 ...在执行任何代码块JVM execute the static code block first之前,然后只运行代码块,因为它已经设计好了。 ..