为什么这不编译(尝试使用java 8和java 10)?它会产生一个缺少的返回语句错误。
public class CompilerIssue {
public boolean run() {
throwIAE();
// Missing return statement
}
public void throwIAE() {
throw new IllegalStateException("error");
}
}
java编译器不知道throwIAE
将始终抛出异常,因此它假设您最终将到达run
方法的末尾,并且当发生这种情况时,需要返回值。
你的方法有一个返回类型,所以它应该返回一个布尔结果。
public boolean run() {
throwIAE();
// Missing return statement
return false;
}
或者你应该直接在方法中抛出异常:
public boolean run() {
throw new IllegalStateException("error"); // it will compile
}
即使编译器现在很聪明,他们也不能“看到”你的throwIAE()
方法总是返回一个异常,因为这将在运行时而不是编译时发生。如果处理异常怎么办?然后,您必须最终添加返回值。
抛出的异常终止了throwIAE
方法,但没有终止调用此方法的方法。将此理解为返回输出的方法(自return;
以来空void
)。
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()
}
到目前为止答案很好。我想知道没人提到AOP(面向方面编程)。使用AOP,您可以在RUNTIME期间轻松拦截您的方法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");
}
}
另一个Aspect类在运行时拦截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!
}
}
如果您的原始类在run()
中没有返回语句而编译,则run()
中的NotReallyACompilerIssue
方法已成功完成且无法返回。哪个不好,是吗?
如果类isfinal
或方法throwIAE isfinal
,则可以检测到这种情况。但情况并非如此,编译器(至少Oracle J8_131)不会进行此类检查。我想这是一个非常具体的案例,不值得努力。