Java中是否存在“noreturn”关键字

时间:2011-04-07 22:39:16

标签: java compiler-construction return

有时我想编写一个error()函数,它最终肯定会调用System.exit(),这意味着该函数永远不会返回。但是,如果我在其他函数中调用error(),我想写如:

int fun() {
...
  error();
}

但是编译器坚持在error()调用之后返回一个int值,因为它不知道error()永远不会返回。 我肯定会返回一个任意的int,但如果返回类型是一个复杂的类,我需要在代码中构造它,这是浪费时间。有没有办法告诉编译器函数永远不会返回?

7 个答案:

答案 0 :(得分:5)

你应该抛出RuntimeException

答案 1 :(得分:5)

在Java方法签名中,您无法告诉编译器该方法无法返回。没有它,编译器别无选择,只能假设它可能会返回。 (实际上,JLS关于可达性/明确赋值的规则将明确说明......如果你愿意通过它们。)

我在两种方法之间摇摆不定:

int fun() {
    ...
    error();
    return 0;  // NOT REACHED
}

int fun() {
    ...
    error();
    throw new AssertionError("not reached");
}

两者都不完全令人满意。

在第一个版本中,评论很重要,因为有人第一次阅读您的代码可能没有意识到error永远不会返回。

第二个版本更强大,因为如果有人更改了error方法的行为以便它实际返回,它会给你“快速失败”。 (第一个版本将导致fun方法返回虚假值......可能导致其他意外后果。)


在相关点上,通过调用System.exit()来拉动JVM上的插件的方法可能会有问题。更好的想法是抛出一个未经检查的“结束世界”异常并将其捕获到主线程的最外层。对于在其他线程上抛出的异常,一个想法是安装一个默认的未捕获异常处理程序,它使用Thread.interrupt()通知主线程已抛出“结束世界”异常。

但重点是代码中的System.exit()次调用是有问题的;例如如果您重新调整代码以在更大的框架内运行;例如在一个网络容器中。

答案 2 :(得分:3)

Java不允许您声明方法永远不会返回,但编译器知道永远不会返回的语句throw

你可以通过声明你的“不回报”来解决这个问题。返回RuntimeException的方法,并使用throw error()进行调用。这样你就可以改变一个不返回"的方法的问题。到一个不返回"的语句。

由于您的error()方法永远不会返回,因此您无需实际返回已声明的RuntimeException,并且throw中的throw error()永远不会被执行。< / p>

这种技术还可以防止error()返回时出现错误,可能是因为某些错误的条件代码。

示例:

private RuntimeException error() {
    throw new EndOfTheWorldException();
    // Java knows that code after throw will not be reached
    // so no return is required here.  Or, if you insist, you
    // could call System.exit() and return null afterwards.
}

int fun() {
    // ...
    throw error();
    // Again, no need for a return here, the compiler understands
    // that the statement above won't return.
}

或者,也许更明确地说,您可以重构此代码以使error()成为抛出异常的工厂:

private RuntimeException makeError() {
    return new EndOfTheWorldException();
}

int fun() {
    throw makeError();
}

答案 3 :(得分:1)

返回0,或者在复杂情况下,返回null。

答案 4 :(得分:1)

不确定为什么要这样做。如果你抛出一个异常,那就是更干净的代码,更可测试和可维护;您可以使用Thread.setDefaultUncaughtExceptionHandler()退出。

但如果你坚持:

public class HaltAndCatchFireError extends Error {
   public HaltAndCatchFireError() {
      System.exit(1);
   }
}

然后你要退出的地方:

int fun() {
   ...
   throw new HaltAndCatchFireError();
}

答案 5 :(得分:0)

你的功能是否会返回任何东西?如果不是,你希望你的功能无效,似乎:

void fun() {

...


}

答案 6 :(得分:-2)

你可以写

error();
return;

但你可能会重新考虑你的方法。这可能不是一个非常面向对象的。