为什么调用另一个引发RuntimeException的方法需要return语句?

Adn*_*M91 1 java exception

为什么javac无法识别无法访问的语句?

public int directThrow(){
     throw new RuntimeException();
    //Compiles fine
}

public int indirectThrow(){
    directThrow();
    // Missing Return Statement error
}
Run Code Online (Sandbox Code Playgroud)

Swe*_*per 7

编译器根本不是设计来分析你的代码很深。

对于directThrow,编译器会查看它并说:“我看到您有一个throw语句,因此该方法将在此处突然终止,然后就不需要return语句!”

对于indirectThrow,编译器查看它并说:“我只看到一个方法调用。嗨,程序员!您需要在这里返回一个语句!”

编译器不会查看directThrow实际执行的操作。我认为这是很合理的,因为与增加编译时间的成本相比,分析您调用的每个方法所执行的操作的收益确实很小。考虑一下编译器需要检查哪些内容,以确保directThrow将始终抛出异常。最重要的是,它是否被任何东西覆盖?你甚至可以检查一下吗?您甚至可以确保将来没有任何类会继承您的类并重写该方法(给您的类,directThrow并且两者都不是final)?

如果您有一些复杂的异常抛出逻辑要提取到方法中,则可以将其提取到返回以下内容的方法中Exception

private Exception someComplicatedLogicThatGivesAnException() { ... }

public void foo() {
    if (...) {
        throw someComplicatedLogicThatGivesAnException();
    }
}
Run Code Online (Sandbox Code Playgroud)


Lin*_*ica 6

反问题:如果 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)返回类型来处理此问题。向编译器指示方法永远无法正常返回。