Java 在抛出 RuntimeException 时需要 return 值
Java expects return value when RuntimeException is thrown
为什么不能编译(用 java 8 和 java 10 试过)?它会产生缺少 return 语句的错误。
public class CompilerIssue {
public boolean run() {
throwIAE();
// Missing return statement
}
public void throwIAE() {
throw new IllegalStateException("error");
}
}
您的方法具有 return 类型,因此它应该 return 布尔结果。
public boolean run() {
throwIAE();
// Missing return statement
return false;
}
或者您应该直接在方法中抛出异常:
public boolean run() {
throw new IllegalStateException("error"); // it will compile
}
java 编译器不知道
throwIAE
总是会抛出异常所以它
假设你最终会到达终点
run
方法和,
当这种情况发生时,
return 值是必需的。
抛出的异常会终止 throwIAE
方法,但不会终止调用此方法的方法。将此理解为返回输出的方法(自 void
以来为空 return;
)。
public void throwIAE() {
return; // is not responsible for terminating run()
}
看到了吗? return
终止 throwIAE
方法,程序继续。 return
和 throw
都与方法本身的范围有关,与调用方法无关。您需要:
public boolean run() {
throwIAE(); // throws exception and terminates throwIAR()
return false; // terminates run()
}
即使现在的编译器很聪明,他们也不能 'see' 你的 throwIAE()
方法总是 return 是一个异常,因为这会在运行时而不是编译时发生。如果你处理异常怎么办?那么你最终必须添加一个return值。
虽然其他答案从用户的角度正确地解释了这种情况,但值得注意的是,分析此类流的“聪明”不是由编译器决定的,而是由 JLS 的规则精确定义的。特别是,§14.21 包含以下内容:
An expression statement can complete normally iff it is reachable.
像throwIAE()
这样的方法调用是一个表达式语句,因为在例子中是可达的,所以也可以“正常完成”。因此,方法体可以“正常完成”,根据 §8.4.7 对于具有非 void return 类型的方法来说是非法的(也就是说,这样的方法必须 return 所有可能路径上的值)。
换句话说,JLS定义了在流分析中所有的方法调用都被平等对待,并没有“method-that-always-throws”这样的概念。
目前回答得很好。我不知道怎么没人提到 AOP(Aspect Oriented Programming)。使用 AOP,您可以在运行时轻松拦截您的方法 throwIAE()
并捕获异常。调用方法 run()
无法知道这一点。
一些例子:
package yourPackage;
public class YourClass {
public boolean run() {
throwIAE();
System.out.println("Hello world!");// prints Hello World! even if method throws exception
return false;// does not compile without return statement
}
public void throwIAE() {
throw new IllegalStateException("error");
}
}
另一个方面 class 在运行时拦截 throwIAE()
方法:
package yourPackage;
@Aspect
public class ExceptionHandlingAspect {
@Around("execution(* yourPackage.YourClass.throwIAE())")
public Object handleException(ProceedingJoinPoint pjp) throws Throwable {
try {
return pjp.proceed();
} catch (Exception e) {
System.out.println("exception caught");
return null;
}
}
}
想象一下:
public class NotReallyACompilerIssue extends CompilerIssue {
@Override
public void throwIAE() {
// doesn't really throw the IAE!
}
}
如果您的原始 class 编译时没有 run()
中的 return 语句,NotReallyACompilerIssue
中的 run()
方法应该成功完成并且没有return。哪个不好,不是吗?
如果class是final
,或者方法throwIAE是final
,就可以检测到这种情况。但事实并非如此,编译器(至少是 Oracle J8_131)不会进行此类检查。我想这是一个非常具体的案例,不值得付出努力。
我真的没想到这会起作用,但有趣的是你可以这样做,这使代码更具可读性:
public static <T> T unsupported()
{
throw new UnsupportedOperationException();
}
...
return unsupported();
为什么不能编译(用 java 8 和 java 10 试过)?它会产生缺少 return 语句的错误。
public class CompilerIssue {
public boolean run() {
throwIAE();
// Missing return statement
}
public void throwIAE() {
throw new IllegalStateException("error");
}
}
您的方法具有 return 类型,因此它应该 return 布尔结果。
public boolean run() {
throwIAE();
// Missing return statement
return false;
}
或者您应该直接在方法中抛出异常:
public boolean run() {
throw new IllegalStateException("error"); // it will compile
}
java 编译器不知道
throwIAE
总是会抛出异常所以它
假设你最终会到达终点
run
方法和,
当这种情况发生时,
return 值是必需的。
抛出的异常会终止 throwIAE
方法,但不会终止调用此方法的方法。将此理解为返回输出的方法(自 void
以来为空 return;
)。
public void throwIAE() {
return; // is not responsible for terminating run()
}
看到了吗? return
终止 throwIAE
方法,程序继续。 return
和 throw
都与方法本身的范围有关,与调用方法无关。您需要:
public boolean run() {
throwIAE(); // throws exception and terminates throwIAR()
return false; // terminates run()
}
即使现在的编译器很聪明,他们也不能 'see' 你的 throwIAE()
方法总是 return 是一个异常,因为这会在运行时而不是编译时发生。如果你处理异常怎么办?那么你最终必须添加一个return值。
虽然其他答案从用户的角度正确地解释了这种情况,但值得注意的是,分析此类流的“聪明”不是由编译器决定的,而是由 JLS 的规则精确定义的。特别是,§14.21 包含以下内容:
An expression statement can complete normally iff it is reachable.
像throwIAE()
这样的方法调用是一个表达式语句,因为在例子中是可达的,所以也可以“正常完成”。因此,方法体可以“正常完成”,根据 §8.4.7 对于具有非 void return 类型的方法来说是非法的(也就是说,这样的方法必须 return 所有可能路径上的值)。
换句话说,JLS定义了在流分析中所有的方法调用都被平等对待,并没有“method-that-always-throws”这样的概念。
目前回答得很好。我不知道怎么没人提到 AOP(Aspect Oriented Programming)。使用 AOP,您可以在运行时轻松拦截您的方法 throwIAE()
并捕获异常。调用方法 run()
无法知道这一点。
一些例子:
package yourPackage;
public class YourClass {
public boolean run() {
throwIAE();
System.out.println("Hello world!");// prints Hello World! even if method throws exception
return false;// does not compile without return statement
}
public void throwIAE() {
throw new IllegalStateException("error");
}
}
另一个方面 class 在运行时拦截 throwIAE()
方法:
package yourPackage;
@Aspect
public class ExceptionHandlingAspect {
@Around("execution(* yourPackage.YourClass.throwIAE())")
public Object handleException(ProceedingJoinPoint pjp) throws Throwable {
try {
return pjp.proceed();
} catch (Exception e) {
System.out.println("exception caught");
return null;
}
}
}
想象一下:
public class NotReallyACompilerIssue extends CompilerIssue {
@Override
public void throwIAE() {
// doesn't really throw the IAE!
}
}
如果您的原始 class 编译时没有 run()
中的 return 语句,NotReallyACompilerIssue
中的 run()
方法应该成功完成并且没有return。哪个不好,不是吗?
如果class是final
,或者方法throwIAE是final
,就可以检测到这种情况。但事实并非如此,编译器(至少是 Oracle J8_131)不会进行此类检查。我想这是一个非常具体的案例,不值得付出努力。
我真的没想到这会起作用,但有趣的是你可以这样做,这使代码更具可读性:
public static <T> T unsupported()
{
throw new UnsupportedOperationException();
}
...
return unsupported();