以静态初始值设定项返回

发布于 2024-08-28 18:52:41 字数 429 浏览 10 评论 0 原文

这不是有效的代码:

public class MyClass
{
    private static boolean yesNo = false;

    static
    {
        if (yesNo)
        {
            System.out.println("Yes");
            return; // The return statement is the problem
        }
        System.exit(0);
    }
}

这是一个愚蠢的示例,但在静态类构造函数中我们无法 return;。 为什么?这有充分的理由吗?有人对此了解更多吗?

所以我应该return的原因是结束那里的构建。

谢谢

This isn't valid code:

public class MyClass
{
    private static boolean yesNo = false;

    static
    {
        if (yesNo)
        {
            System.out.println("Yes");
            return; // The return statement is the problem
        }
        System.exit(0);
    }
}

This is a stupid example, but in a static class constructor we can't return;.
Why? Are there good reasons for this? Does someone know something more about this?

So the reason why I should do return is to end constructing there.

Thanks

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

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

发布评论

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

评论(6

谁许谁一生繁华 2024-09-04 18:52:41

我认为原因是初始化器与字段初始化一起进行(在实例初始化器的情况下,还与构造函数一起进行)。换句话说,JVM 只识别一个地方来初始化静态字段,因此所有初始化(无论是否在块中)都必须在那里完成。

因此,例如,当您编写一个类时:

class A {
    static int x = 3;
    static {
        y = x * x;
    }
    static int z = x * x;
}

那么实际上就像您编写了:

class A {
    static int x, y, z;
    static {
        x = 3;
        y = x * x;
        z = x * x;
    }
}

如果您查看反汇编,则可以确认这一点:

static {};
  Code:
   0:   iconst_3
   1:   putstatic       #5; //Field x:I
   4:   getstatic       #5; //Field x:I
   7:   getstatic       #5; //Field x:I
   10:  imul
   11:  putstatic       #3; //Field y:I
   14:  getstatic       #5; //Field x:I
   17:  getstatic       #5; //Field x:I
   20:  imul
   21:  putstatic       #6; //Field z:I
   24:  return

因此,如果您在静态初始值设定项中间的某个位置添加了“返回”,则也会阻止 z 的计算。

I think the reason is that initializers are carried together with field initializations (and with constructors, in the case of instance initializers). In other words, the JVM only recognizes one place to initialize static fields, and thus all initializations - whether in blocks or not - must be done there.

So, for example, when you write a class:

class A {
    static int x = 3;
    static {
        y = x * x;
    }
    static int z = x * x;
}

Then it's actually as if you've written:

class A {
    static int x, y, z;
    static {
        x = 3;
        y = x * x;
        z = x * x;
    }
}

This is confirmed if you look at the disassembly:

static {};
  Code:
   0:   iconst_3
   1:   putstatic       #5; //Field x:I
   4:   getstatic       #5; //Field x:I
   7:   getstatic       #5; //Field x:I
   10:  imul
   11:  putstatic       #3; //Field y:I
   14:  getstatic       #5; //Field x:I
   17:  getstatic       #5; //Field x:I
   20:  imul
   21:  putstatic       #6; //Field z:I
   24:  return

So if you would have added a "return" somewhere in the middle of your static initializer it would also have prevented z from being calculated.

临风闻羌笛 2024-09-04 18:52:41
  • 程序流程始终可以构造为无需返回。 (在您的示例中,将 System.exit(0) 放在 else 子句中将达到所需的结果)

  • 如果您确实需要它,您可以将代码移入静态方法并从初始值设定项调用它:

static {
    staticInit();
}

private static void staticInit() {
    if (yesNo) {
        System.out.println("Yes");
        return;
    }
    System.exit(0);
}

请注意,这不是静态构造函数,而是静态初始值设定项。什么都没有被构建。

  • the program flow can always be structured to go without the need for return. (In your example putting System.exit(0) in an else clause would achieve the desired result)

  • in you really need it, you can move the code in a static method and call it from the initializer:

.

static {
    staticInit();
}

private static void staticInit() {
    if (yesNo) {
        System.out.println("Yes");
        return;
    }
    System.exit(0);
}

Note that this is not a static constructor, it's a static initializer. Nothing gets constructed.

萌吟 2024-09-04 18:52:41

来自 关于静态初始化器的 JSL

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

突然完成(除其他外):“没有值返回”、“返回给定值”等。

因此,静态初始化程序中的 return 语句是“突然完成”并会产生编译时错误。

From JSL regarding static initializers:

"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)."

Abrupt completion (among others): "return with no value", "return with a given value", etc.

So a return statement in a static initializer is an "abrupt completion" and produces a compile-time error.

绝對不後悔。 2024-09-04 18:52:41

你应该回到什么?在静态初始化程序中没有调用者,因此就我而言,返回没有意义。静态初始化器在类第一次加载时执行。

What should you return to? In a static initializer there is no caller, so a return doesn't make sense as far as I see it. Static initializers are executed when the class is loaded for the first time.

你另情深 2024-09-04 18:52:41

我知道静态初始化程序的规则是它们仅在加载类字节码之后、执行任何静态方法或实例化类中的第一个对象之前执行一次。 JLS 保证该初始化已完成。为了确保这一保证是真实的,JLS 还指定代码不能突然终止(如另一个答案中明确给出的)。

请注意,可以在不初始化字节码的情况下加载它;请参阅 Class.forName(String, boolean, ClassLoader) 方法。如果 boolean 参数为 false 那么这将加载该类但不会初始化它。程序员仍然可以进行一些反射来发现有关该类的信息,而无需对其进行初始化。但是,一旦您尝试通过调用静态方法或实例化实例来直接使用该类,那么 JVM 将首先对其进行初始化。

如果任何静态初始化程序突然终止(这可能会因 RuntimeException 而发生),则该类将处于无效状态。第一次,JVM 将抛出 ExceptionInInitializeError(请注意,这是一个 Error,这意味着它被视为内部故障)。从那时起,将无法使用该类 - 尝试调用静态方法或实例化对象时,您将收到 NoClassDefFoundError

在不重新启动 JVM 的情况下从这种情况中恢复的唯一方法是,如果您正在使用 ClassLoader,并且可以用失败的类替换类加载器,并在不同的环境(可能是不同的系统)中重建类或重新初始化程序属性),但是程序必须为这种情况做好充分准备。

I understand that the rule for static initializers is that they are only every executed one time, after the class byte-code is loaded and before executing any static method or instantiating the first object from the class. The JLS guarantees that this initialization will have been completed. To ensure that this guarantee is true, the JLS also specifies that the code cannot have been abruptly terminated (as given clearly in another answer).

Note that it is possible to load byte-code without initializing it; see Class.forName(String, boolean, ClassLoader) method. If the boolean parameter is false then this will load the class but not initialize it. The programmer can still do some reflection to discover information about that class still without it being initialized. However, once you attempt to use the class directly by calling a static method or instantiating an instance, then the JVM will proceed to initialize it first.

If any of the static initializers do abruptly terminate - which can happen with a RuntimeException, the class will be left in an invalid state. The first time, the JVM will throw an ExceptionInInitializeError (notice that is an Error which means it is considered an internal failure). From that point on it will not be possible to use the class - attempting to call a static method or instantiating an object you will instead get a NoClassDefFoundError.

The only way to recover from this situation without restarting the JVM is if you are using ClassLoaders and can replace the class loader with the failed class and rebuild the class or reinitializer in a different environment (perhaps different system properties), but the program must then be well prepared for this kind of situation.

贵在坚持 2024-09-04 18:52:41

我会重新排序该声明,使其更简单/更短。 if/else 的两个分支都需要返回的情况永远不会出现。

static { 
    if (!yesNo) 
       System.exit(0); // silently exiting a program is a bad idea!"
    System.out.println("Yes"); 
} 

I would reorder the statement, making it simpler/shorter. There will never be a good case where both branches of if/else need a return.

static { 
    if (!yesNo) 
       System.exit(0); // silently exiting a program is a bad idea!"
    System.out.println("Yes"); 
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文