当我们第一次使用一个类时,静态代码总是被执行吗?

发布于 2024-09-08 11:52:34 字数 907 浏览 6 评论 0原文

我们的应用程序使用的初始化代码取决于静态代码的执行顺序,我想知道这个顺序在所有 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;
}

will Give:

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;
}

will Give (在我的环境中):

mainValue

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

Our application is using initialization code that depends on the order static code is executed and I'm wondering if this order will be consistent across all JVMs.

Here is a sample of what I mean:


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;
}

will give:

init_value
init_value

and


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;
}

will give (on my environment):

mainValue

To summarize, across all JVMs, is static code always executed when we use a class for the first time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

你穿错了嫁妆 2024-09-15 11:52:34

编辑:尽管有下面的所有保证,如果您正在考虑依赖这种事情,我会尽力重构您的代码,以便它不会突然出现。虽然它保证可以工作,但它也可能使您的代码变得非常脆弱。静态初始化器被“无形地”调用这一事实使得它们相对难以推理和调试。


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

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

StaticInitializer:静态

静态初始化器能够突然完成(第 14.1 节,第 15.6 节)并带有受检查异常(第 11.2 节),这是一个编译时错误。如果静态初始化程序无法正常完成,则这是一个编译时错误(第 14.21 节)。

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

以及第 12.4 节

类的初始化包括
执行其静态初始化程序和
静态字段的初始值设定项
在类中声明。初始化
接口的组成包括执行
声明的字段的初始值设定项
在界面中。

上课前
已初始化,其直接超类
必须初始化,但接口
不需要由类实现
已初始化。同样,
接口需要的超级接口
之前没有被初始化
接口已初始化。

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

  • T 是一个类,T 的一个实例是
    创建。
  • T 是一个类,也是一个静态变量
    调用 T 声明的方法。
  • A
    T 声明的静态字段是
    已分配。
  • T 声明的静态字段
    已使用且该字段不是
    常量变量(第 4.12.4 节)。
  • T 是一个
    顶级类和断言
    语句 (§14.10) 词法嵌套

EDIT: Despite all the reassurances below, if you're thinking of relying on this sort of thing, I would try hard to refactor your code so that it doesn't crop up. While it is guaranteed to work, it's also likely to make your code very brittle. The fact that static initializers get called "invisibly" makes them relatively hard to reason about and debug.


Yes, this is guaranteed by the language specification. From section 8.7 of the spec:

Any static initializers declared in a class are executed when the class is initialized and, together with any field initializers (§8.3.2) for class variables, may be used to initialize the class variables of the class (§12.4).

StaticInitializer: static Block

It is a compile-time error for a static initializer to be able to complete abruptly (§14.1, §15.6) with a checked exception (§11.2). It is a compile-time error if a static initializer cannot complete normally (§14.21).

The static initializers and class variable initializers are executed in textual order.

And from section 12.4:

Initialization of a class consists of
executing its static initializers and
the initializers for static fields
declared in the class. Initialization
of an interface consists of executing
the initializers for fields declared
in the interface.

Before a class is
initialized, its direct superclass
must be initialized, but interfaces
implemented by the class need not be
initialized. Similarly, the
superinterfaces of an interface need
not be initialized before the
interface is initialized.

A class or interface type T will be
initialized immediately before the
first occurrence of any one of the
following:

  • T is a class and an instance of T is
    created.
  • T is a class and a static
    method declared by T is invoked.
  • A
    static field declared by T is
    assigned.
  • A static field declared by T
    is used and the field is not a
    constant variable (§4.12.4).
  • T is a
    top-level class, and an assert
    statement (§14.10) lexically nested
天气好吗我好吗 2024-09-15 11:52:34

当您第一次使用一个类时,静态初始化程序(例如您的 staticVar 声明)总是被执行。

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

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

static {
  // some initialisation code here
}

Static initialisers (e.g. your staticVar declarations) are always executed when you use a class for the first time.

Static methods are only executed when they are called. In your case, this is happening because the static void main(String[] args) is the entry point to your application. But if you defined a different static method then it would not be called.

It is also possible to create a static initialiser block that will also be called automatically before the class is first used, e.g.

static {
  // some initialisation code here
}
她如夕阳 2024-09-15 11:52:34

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

That should be all the same on all platforms. See JVM Specification : http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#19075

两人的回忆 2024-09-15 11:52:34

引用 Java 规范:

的初始化包括
执行其静态初始化程序和
静态字段的初始值设定项
在类中声明。初始化
接口的组成包括执行
声明的字段的初始值设定项
在界面中。

A quote from Java specification:

Initialization of a class consists of
executing its static initializers and
the initializers for static fields
declared in the class. Initialization
of an interface consists of executing
the initializers for fields declared
in the interface.

寻找我们的幸福 2024-09-15 11:52:34

是的,根据 Java 语言规范静态代码始终在所有(兼容的)JVM 上以相同的顺序执行。

8.7 静态初始化器

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

Yes, according to the Java Language Specification static code is always executed in the same order on all (compliant) JVM's.

8.7 Static Initializers

The static initializers and class variable initializers are executed in textual order.

孤单情人 2024-09-15 11:52:34

与其他海报相同,但让我补充一点,在我看来,依赖于其他类的状态的静态初始化程序(如您的示例)似乎会导致非常脆弱且难以维护的代码。我将使用静态初始化器来填充内部类数据——用默认值或类似的东西填充数组。但我想我从来没有看过另一堂课的数据。从技术上讲是合法的,也许在某些奇怪的情况下这是个好主意,但是很糟糕。

Dittos to other posters, but let me add that a static initializer that depends on the state of other classes like in your example seems to me to make for very fragile and difficult-to-maintain code. I'll use static intializers to populate internal class data -- to fill up an array with default values or that sort of thing. But I don't think I've ever had one peek at the data in another class. Technically legal, and maybe there are odd cases where it's a good idea, but yuck.

枯寂 2024-09-15 11:52:34

是的,我相信这就是定义的重点。

Yes, I believe that would be the point by definition.

り繁华旳梦境 2024-09-15 11:52:34

静态块总是首先运行,而不仅仅是第一次...在执行任何代码块之前,JVM首先执行静态代码块,然后才运行该代码块因为它已经被设计...

Static Block will always run first not just the first time... Before executing any code block, JVM execute the static code block first, and then only it run the code block as it has been designed...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文