这不是有效的代码:
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
的原因是结束那里的建设。
由于
答案 0 :(得分:15)
我认为原因是初始化器与字段初始化一起进行(对于构造函数,在实例初始化器的情况下)。换句话说,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的计算。
答案 1 :(得分:10)
程序流程始终可以构建为不需要return
。 (在您的示例中,将System.exit(0)
放在else
子句中可以获得所需的结果)
你真的需要它,你可以用静态方法移动代码并从初始化程序中调用它:
static {
staticInit();
}
private static void staticInit() {
if (yesNo) {
System.out.println("Yes");
return;
}
System.exit(0);
}
请注意,这不是静态构造函数,它是静态初始化程序。什么都没有建成。
答案 2 :(得分:2)
你应该回归什么?在静态初始化器中没有调用者,所以就我看来,返回没有意义。第一次加载类时执行静态初始值设定项。
答案 3 :(得分:1)
来自JSL regarding static initializers:
“静态初始化程序能够使用已检查的异常(第11.2节)突然完成(第14.1节,第15.6节)是一个编译时错误。如果静态初始化程序无法完成,则是编译时错误通常(§14.21)。“
Abrupt completion(除其他外):“没有价值的回报”,“给定价值的回报”等等。
因此静态初始化程序中的return语句是“突然完成”并产生编译时错误。
答案 4 :(得分:0)
我理解静态初始化程序的规则是它们只是在加载类字节代码之后,在执行任何静态方法或从类中实例化第一个对象之前,每次执行一次。 JLS保证此初始化已完成。为确保此保证为真,JLS还指定代码不能突然终止(在另一个答案中明确说明)。
请注意,可以在不初始化的情况下加载字节码;请参阅Class.forName(String, boolean, ClassLoader)方法。如果boolean
参数为false
,那么这将加载类但不初始化它。程序员仍然可以做一些反思,以便在没有初始化的情况下仍然发现有关该类的信息。但是,一旦尝试通过调用静态方法或实例化实例来直接使用该类,JVM将首先进行初始化。
如果任何静态初始值设定项突然终止 - 这可能发生在RuntimeException
,则该类将保持无效状态。第一次,JVM将抛出ExceptionInInitializeError
(通知是Error
,这意味着它被视为内部故障)。从那时起,将无法使用该类 - 尝试调用静态方法或实例化对象,而不是NoClassDefFoundError
。
在不重新启动JVM的情况下从这种情况中恢复的唯一方法是使用ClassLoader
并且可以用失败的类替换类加载器并在不同的环境中重建类或重新初始化器(可能是不同的系统)属性),但程序必须为这种情况做好充分准备。
答案 5 :(得分:0)
我会重新排序声明,使其更简单/更短。永远不会有一个好的情况,if / else的两个分支都需要返回。
static {
if (!yesNo)
System.exit(0); // silently exiting a program is a bad idea!"
System.out.println("Yes");
}