在Java中完全打开枚举会产生“缺少返回语句”错误
假设,我们有一个switch语句,它完全覆盖了枚举参数的所有可能情况,并且也有空检查,由于"Missing return statement"
的原因,它不会被编译
enum Foo {ONE,TWO}
int fooToInt(Foo foo) {
if (foo == null) {
throw new NullPointerException();
}
switch (foo) {
case ONE: return 1;
case TWO: return 2;
}
}
我知道,从default
案例或在enum之后抛出异常,或者访问enum元素而不是switch
将解决问题。但我不理解这种行为的技术原因:显然,不存在不导致return
或throw
的可能的执行分支。此外,在某些情况下,最好在编译时检查是否涵盖了所有情况
# 1 楼答案
你错过了
default
块因为你的方法必须返回一些值
将return置于switch语句之外。或放置默认值块
# 2 楼答案
在这里我将在黑暗中试一试,没有读到任何理由,但如果这不是行为的主要原因,至少是一个原因
假设enum来自项目所依赖的库。在您编译的版本中,)。如果
ONE
和TWO
是唯一的选项。但是,您可能会在一个更高版本(通过OSGi或其他解决方案)上运行,该版本增加了另一个价值^{THREE
被传递到fooToInt
,它将到达方法的末尾,并且不会返回(或抛出)任何内容。哎呀这在运行时很难发现,因此您不得不选择如何处理它,即使在编译时它实际上看起来不可能。有些情况,比如您的示例中的情况,可能会被检测到并允许编译,而另一些情况可能会得到不同的处理(例如隐式的^{),但在所有可以改进Java的事情列表中,我不会把它放在首位
# 3 楼答案
原因是编译器实际上并没有通过你的开关来检查你是否实现了每一个case,它只是检查现有的case是否与Foo中的实际值相对应——因此它需要一些东西,要么是默认块,要么是返回
# 4 楼答案
由于没有编写默认值,编译器会在开关块后的下一行自动添加它。此时,编译器会“注意”该方法没有返回点,并给出该错误
我以您为例进行了更改,但在切换后添加了RuntimeException抛出,如下所示:
我编译了这个类,并使用了javap-c示例。类以查看实际字节码(请参见下文)。注意javac添加的“default:52”。 它将引导到switch case之后的block部分,在那里,我抛出了RuntimeException,它覆盖了返回的需要
# 5 楼答案
编译器不会检查是否已将
Foo
中的所有常量列为case
块,从而引发错误假设
Foo
被定义为:那么,如果将
Foo.THREE
作为参数传递,您的方法将返回什么作为
switch
方法的替代方法,您可以在Foo
枚举中添加int
成员,并为每个常量设置相应的数字:这样你就不需要
switch
了,编译器会要求你为任何可能的新Foo
常量设置一个相应的数字