java - 是否可以将多个异常收集到一个自定义异常中?
问题描述
由于重构原因使用反射 API,我需要抛出重复出现的异常:
throws ApiException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException
这些异常总是出现在我使用重构方法的方法中,是否可以这样做:
throws CustomException
处理上面提到的所有异常?谢谢
解决方案
是的。有两种方法可以做到这一点:
类层次结构
这仅适用于您是设计例外的人。如果这不能描述这种情况,请继续下一章。
例如,如果您有一个用户身份验证 API,您可能想要创建一整套异常,例如UserNotFoundException
、IncorrectPasswordException
、UserFrozenException
、IpBlockedException
等等。
如果您确保所有这些异常都扩展了一个异常类型 ( AuthenticationException
),如下所示:
public class AuthenticationException extends Exception {
public AuthenticationException(String msg, Throwable cause) {
super(msg, cause);
}
public AuthenticationException(String msg) {
super(msg);
}
}
public class UserNotFoundException extends AuthenticationException {
public UserNotFoundException(String username) {
super(username);
}
}
// and so on
然后调用者可以选择,这就是为什么这会产生如此出色的 API 设计。
如果调用者需要根据发生的身份验证问题的类型进行自定义反应,他们可以捕获,例如,UserNotFoundException
. 但如果他们不是特别在意,他们可以抓住AuthenticationException
。
请注意,java 本身也这样做。GeneralSecurityException是常见的超类,但大多数与安全相关的方法都会抛出一个相当大的子类列表,这样调用者就可以准确地知道会发生什么样的错误,并且可以为特定的错误编写处理程序,而无需强迫他们编写大量的如果他们不想,就抓住块。
重新抛出
另一种解决方案是将异常捆绑到您自己的自定义类型中。
为此,首先编写一个异常(或使用现有的异常,但这在风格上很少是正确的举动)。然后,编写一个 catch 块并将所有那些奇怪的、不相关的异常包装到这个新创建的异常中,确保使用“原因”系统:
public class CustomException { // find a better name
public CustomException(String msg, Throwable cause) {
super(msg, cause);
}
public CustomException(String msg) {
super(msg);
}
public CustomException(Throwable cause) {
super(cause);
}
}
public void myMethod() throws CustomException {
try {
// code here
} catch (ApiException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) {
throw new CustomException(e);
} catch (InvocationTargetException e) {
throw new CustomException(e.getCause();
}
}
但请注意,您只想一劳永逸的建议如何导致您的 API 设计出现问题。例如,像这样包装 InvocationTargetException 对您的 API 使用者来说是相当不利的;InvocationTargetException 本身就是一个包装器,所以现在你有了 wrappers-in-wrappers-in-wrappers ,这很丑陋,而且很难调用代码甚至试图以精确的方式处理问题。要阅读您使用的 API 并理解它为什么会抛出它抛出的各种异常,确实没有简单的方法。
注意:如果可以的话,类层次结构解决方案是一种更好的方法;但它确实要求您控制抛出它们的代码。
推荐阅读
- hammerspoon - 如何使用 hotkey.bind 绑定多个键?
- javascript - 在闪亮的应用程序中按下时,播放在另一个弹出模式中以模式显示的 youtube 视频
- android - 当我使用 admob 颤振时位置参数太多
- html - Angular Material mat-card-content 和 mat-card-actions:如何更改这两者之间的间距?
- reactjs - 在名为 Cb 的 React JS 中出现错误从未调用过!错误并尝试了互联网上所有可用的解决方案,但没有奏效
- css - 无论使用哪种移动设备,我该如何管理,至少有 2 张图像彼此相邻?
- android - 更改已编译共享库的导出函数名称
- jenkins - Jenkins 中的卷曲用法
- reactjs - 如何在突变和重新获取期间显示微调器?
- reactjs - 使用 React js 和 Firebase 进行表单验证