【发布时间】:2017-09-16 11:06:11
【问题描述】:
class TestCase{
static{
System.out.println("hello");
return;
}
public static void main(String[] args){
System.out.println("main");
}
}
【问题讨论】:
标签: java initializer
class TestCase{
static{
System.out.println("hello");
return;
}
public static void main(String[] args){
System.out.println("main");
}
}
【问题讨论】:
标签: java initializer
static 块用于初始化static 变量,不需要在一个内调用return 或throw 和Exception。
如果您需要到return 或throw 和Exception,那么我建议您使用Java™ 静态初始化块教程中所说的去做并分配一个方法:
class Whatever {
public static varType myVar = initializeClassVariable();
private static varType initializeClassVariable() {
// initialization code goes here
}
}
取自https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
【讨论】:
不允许使用return,因为严格来说静态块不是一种方法。没有“调用者”可以返回,当然也没有什么可以返回值。另外,只要稍微重构一下代码,总能达到return-with-no-expression的局部流控效果。
(在您的示例中,return 无论如何都是多余的......从本地流量控制的角度来看。)
简而言之,return 是不允许的,因为它没有意义。 (就像您不能在不在循环语句中的代码中使用 continue。)
从静态块传播出来的异常是有问题的。基本上,应用程序代码无法捕捉和处理它们。
checked/unchecked 区分的重点是确保某些异常不能被忽略。因此,Java 语言将传播已检查异常的静态块视为编译错误。
另一方面,允许在静态块中抛出未经检查的异常(并且不被捕获)。这会导致ExceptionInInitializerError,并使您尝试初始化的类处于“死”状态。通常,应用程序无法从中恢复。
为什么允许这样做?鉴于可能出现未经检查的异常的多种方式,Java 语言坚持在静态初始化程序块内处理它们是不切实际的。此外,意外+未经检查的异常实际上是一个应用程序错误。处理错误的最简单/最安全的方法是让应用程序死掉……为程序员诊断和修复错误留下证据。
【讨论】:
continue 在任意块中可能有意义;这将是一个落后的goto。
这个问题也适用于实例初始化器以及静态初始化器。
return 语句可以被允许,它与void 方法中的return 一样有用。但是,我认为最大的问题是存在多个初始化程序时的歧义:
static{ // 1
...
...return;
...
}
static{ // 2
...
}
如果return被执行,是直接终止块1,继续块2,还是终止所有的静态初始化代码?
throw的问题见Why is it not allowed to throw an exception in a Java instance initialization block?
我的理解是,如果静态/实例初始化器无条件地抛出异常,则类/构造器总是会失败,使其几乎毫无用处。因此 Java 禁止它。
解决方法:
return 可以由 break 从标记块模拟:
static
{
STATIC:
{
break STATIC;
}
}
无条件throw可以通过if(true)实现
static
{
if(true) throw new Error();
}
(Java专门假装不知道该语句肯定被执行)
【讨论】:
因为它们不能被声明为返回值或抛出异常。它们本质上是匿名的static void 方法,不会抛出检查异常。
【讨论】:
RuntimeExceptions或Errors,这样做的结果正如你所描述的那样。它们不能抛出 checked 异常,因为编译器不允许它们。
exception 被捕获,那么对象的状态是什么 - 构造与否?
static { throw new Error("y"); } 将导致立即编译错误。