为什么javac无法识别无法访问的语句?
public int directThrow(){
throw new RuntimeException();
//Compiles fine
}
public int indirectThrow(){
directThrow();
// Missing Return Statement error
}
答案 0 :(得分:6)
编译器并非旨在深入分析您的代码。
对于directThrow
,编译器会查看它并说:“我看到您有一个throw语句,因此该方法将在此处突然终止,然后不需要return语句!”
对于indirectThrow
,编译器会查看它并说:“我只看到一个方法调用。嗨,程序员!您需要在这里返回语句!”
编译器不会查看directThrow
的实际作用。我认为这是相当合理的,因为与增加编译时间的成本相比,分析您调用的每种方法的作用的确很小。考虑一下编译器需要检查哪些内容,以确保directThrow
始终会引发异常。最重要的是,它是否被任何东西覆盖?你甚至可以检查一下吗?您甚至可以确保将来没有任何类会继承您的类并重写该方法(给您的类和directThrow
都不是{final
)?
如果要将某些复杂的异常抛出逻辑提取到方法中,则可以将其提取到返回Exception
的方法中:
private Exception someComplicatedLogicThatGivesAnException() { ... }
public void foo() {
if (...) {
throw someComplicatedLogicThatGivesAnException();
}
}
答案 1 :(得分:5)
计数器问题: if directThrow()
发生了什么变化,使其没有引发异常?代码应如何处理呢?
为说明此问题,下面是一个示例:
class Foo {
int throwSomething() {
throw new RuntimeException();
}
}
class Bar extends Foo{
int throwSomething() {
return 1; // hahaaa, we don't throw but return normally
}
}
看到了吗?子类重写基本方法,并返回一些信息,代码现在应如何处理该问题:
int indirectThrowing(Foo foo) {
foo.throwSomething();
}
如果我们通过new Foo()
,它将按预期方式抛出,但如果我们通过new Bar()
,它将仅返回1
。因此,它不会失败。
要解决此问题,您必须编写一个return语句。或者,如果您想重用已有的东西,还可以编写:
return directThrow();
由于directThrow()
的返回类型为int
,因此您只需向上传递参数即可。
请注意,某些语言(例如Kotlin)使用Nothing
(有时也称为Never
)返回类型来处理此问题。向编译器指示方法永远无法正常返回。