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