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

时间:2019-05-31 09:39:20

标签: java exception

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

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

public int indirectThrow(){
    directThrow();
    // Missing Return Statement error
}

2 个答案:

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