以静态初始值设定项返回
这不是有效的代码:
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
的原因是结束那里的构建。
谢谢
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我认为原因是初始化器与字段初始化一起进行(在实例初始化器的情况下,还与构造函数一起进行)。换句话说,JVM 只识别一个地方来初始化静态字段,因此所有初始化(无论是否在块中)都必须在那里完成。
因此,例如,当您编写一个类时:
那么实际上就像您编写了:
如果您查看反汇编,则可以确认这一点:
因此,如果您在静态初始值设定项中间的某个位置添加了“返回”,则也会阻止 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:
Then it's actually as if you've written:
This is confirmed if you look at the disassembly:
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.
程序流程始终可以构造为无需
返回
。 (在您的示例中,将System.exit(0)
放在else
子句中将达到所需的结果)如果您确实需要它,您可以将代码移入静态方法并从初始值设定项调用它:
。
请注意,这不是静态构造函数,而是静态初始值设定项。什么都没有被构建。
the program flow can always be structured to go without the need for
return
. (In your example puttingSystem.exit(0)
in anelse
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:
.
Note that this is not a static constructor, it's a static initializer. Nothing gets constructed.
来自 关于静态初始化器的 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.
你应该回到什么?在静态初始化程序中没有调用者,因此就我而言,返回没有意义。静态初始化器在类第一次加载时执行。
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.
我知道静态初始化程序的规则是它们仅在加载类字节码之后、执行任何静态方法或实例化类中的第一个对象之前执行一次。 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 isfalse
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 anExceptionInInitializeError
(notice that is anError
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 aNoClassDefFoundError
.The only way to recover from this situation without restarting the JVM is if you are using
ClassLoader
s 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.我会重新排序该声明,使其更简单/更短。 if/else 的两个分支都需要返回的情况永远不会出现。
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.