我写了一个在try语句中返回一些值的方法。在 catch 中,我调用 handleException,它将具有理解异常和重新抛出新异常的转换逻辑。这里handleException总是抛出异常,getXYZ()仍然给出编译时错误,期望返回语句。我不是在处理异常,我只是抛出新的异常,那么为什么该方法需要 return 语句。
public String getXYZ(String input) {
try {
return getFromDAO(input);
} catch (Exception e) {
handleException(e);
}
}
private void handleException(Exception e) {
try {
throw e;
} catch(SomeException se) {
throw new MyRuntimeException("MyException message", se);
} catch(SomeOtherException soe) {
throw new MyRuntimeException("MyException message", soe);
}
}
此方法的另一个版本将编译。
public String getXYZ(String input) {
try {
return getFromDAO(input);
} catch (Exception e) {
throw e;
}
}
您没有在 catch
块中抛出任何内容,而是在调用句柄函数,这最终会导致抛出新的异常,但 getXYZ
中的实际代码正在catch
中执行函数调用。 如果在某些情况下将handleException
更改为稍后不抛出异常,那么getXYZ
返回什么?
解决此问题的一种方法是向编译器明确表示您希望引发异常。
public String getXYZ(String input) {
try {
return getFromDAO(input);
} catch (Exception e) {
throw handleException(e); // compiles ok.
}
}
private RuntimeException handleException(Exception e) {
try {
throw e;
} catch(SomeException se) {
return new MyRuntimeException("MyException message", se);
} catch(SomeOtherException soe) {
return new MyRuntimeException("MyException message", soe);
} catch(RuntimeException re) {
return re;
} catch(Exception e2) {
return new MyRuntimeException("MyException message", e2);
}
}
顺便说一句,另一种方法是根本不包装异常并保留异常。
public String getXYZ(String input) {
try {
return getFromDAO(input);
} catch (Exception e) {
throw rethrow(e); // compiles ok.
}
}
/**
* Cast a CheckedException as an unchecked one.
*
* @param throwable to cast
* @param <T> the type of the Throwable
* @return this method will never return a Throwable instance, it will just throw it.
* @throws T the throwable as an unchecked throwable
*/
@SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
throw (T) throwable; // rely on vacuous cast
}
您可能还需要考虑使用新的 java 8 lambda 功能来解决您的问题。您必须创建一个函数接口来声明 lambda 的签名(相关例外)。您的 handleException 方法现在将是运行 lambda 并处理异常的方法。
public String getXYZ(String input) {
return handleKnownExceptions(() -> getFromDAO(input));
}
private <T> T handleKnownExceptions(ThrowingCode<T> throwingCode)
{
try {
return throwingCode.get();
} catch(SomeException se) {
throw new MyRuntimeException("MyException message", se);
} catch(SomeOtherException soe) {
throw new MyRuntimeException("MyException message", soe);
}
}
@FunctionalInterface
public interface ThrowingCode<T>
{
T get() throws SomeException, SomeOtherException;
}
我见过几次处理这种情况的模式。让 handleException
方法声明它返回异常。这只是指示性的,它永远不会返回任何东西,它总是会抛出,就像以前一样。声明的返回类型将允许调用方使用 throw handleException()
语句,这将使编译器满意。生成的代码将是:
public String getXYZ(String input) throws Exception {
try {
return getFromDAO(input);
} catch (Exception e) {
throw handleException(e);
}
}
/**
* This method will never return normally, always throws.
*/
private Exception handleException(Exception e) throws Exception
{
try {
throw e;
} catch(SomeException se) {
throw new MyRuntimeException("MyException message", se);
} catch(SomeOtherException soe) {
throw new MyRuntimeException("MyException message", soe);
}
}