java - 从层次结构中捕获显式异常
问题描述
我在一个名为ServiceException
. 这些异常包括服务失败的明确原因 - BadRequestException
,ServiceUnreachableException
以指示我的类无法自行修复的行为。
这个层次结构看起来有点像这样:
public class ServiceException extends Exception {
public ServiceException() { super(); }
public ServiceException(String message) { super(message); }
public ServiceException(String message, Throwable cause) { super(message, cause); }
public ServiceException(Throwable cause) { super(cause); }
}
以及其中一种子类型的示例:
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class ServiceUnreachableException extends ServiceException {
private final String message;
private final Throwable cause;
}
当我去使用它时,我希望有以下结构:
public void doProcess() throws ServiceException {
...
}
public void processor() {
try {
doProcess()
} catch (BadRequestException e) {
// Handle specific exception
} catch (ServiceUnreachableException e) {
// etc
} catch (InvalidApiKeyException e) {
// ...
}
}
这使我能够干净地使用 catch 块来捕获各种异常。尽管 Java 似乎无法推断出异常是由doProcess
方法显式通过throws ServiceException
.
这会让我相信我需要执行以下操作之一:
public void doProcess() throws BadRequestException, ServiceUnreachableException, InvalidApiKeyException {
...
}
public void processor() {
try {
doProcess();
} catch (BadRequestException e) {
// Handle specific exception
} catch (ServiceUnreachableException e) {
// etc
} catch (InvalidApiKeyException e) {
// ...
}
}
或者
public void doProcess() throws ServiceException {
...
}
public void processor() {
try {
doProcess();
} catch (ServiceException e) {
if(e instanceof BadRequestException) {
// cast and do stuff
} else if(e instanceof ServiceUnreachableException) {
// cast and do stuff
} else if(e instanceof InvalidApiKeyException) {
//cast and do stuff
}
}
}
为了换取更干净的doProcess
方法定义,这似乎更混乱。
这里哪个更正确?它们都可以工作,但我觉得这个catch
版本是你应该使用异常的方式,另一个是一团糟,因为doProcess
决定通过不显式枚举它抛出的所有异常来节省几行。
谢谢!
解决方案
尽管 Java 似乎无法推断出异常是由
doProcess
方法显式通过throws ServiceException
.
不,它不能,因为它无法确信它知道ServiceException
现在存在或将来可能存在的所有子类。
这里哪个更正确?
这不是正确性的问题。这两种方法都可以完成工作。但我认为捕获一般异常然后使用条件表达式为特定子类型选择行为的方式很糟糕。您应该使用catch
块将处理程序与特定异常相关联。
但我认为你问错了问题。请注意,还有第三种选择至少与第一种一样好:
public void doProcess() throws ServiceException {
...
}
public void processor() {
try {
doProcess();
} catch (BadRequestException e) {
// Handle specific exception
} catch (ServiceUnreachableException e) {
// etc
} catch (InvalidApiKeyException e) {
// ...
} catch (ServiceException e) {
// fallback for any other flavor of ServiceException
// ...
}
}
当然,这假设您要避免processor()
声明任何已检查的异常;否则你也可以拥有它,ServiceException
而不是为它提供一个通用的 catch 块。
因此,您应该问的问题不是如何捕捉而是扔什么。这是一个设计考虑,我们没有足够的信息来发表意见。
推荐阅读
- sql - 如何按字段过滤包含另一个字段
- android - 如何将文件映射上传到php服务器
- javascript - 如何分别从数组中获取项目
- wpf - 如何将 IAsyncQuickInfoSource 工具提示中的 WPF 文本框的文本复制到剪贴板
- android - Flutter 正在同时安装两个应用
- c# - 运行所有 Start 方法后创建事件链
- php - 将邮件发送给电子邮件地址来自 Mysql 的不同用户
- mysql - 无法在 Redhat Openshift 上部署 MySQL
- linux - Electron Linux:.AppImage 未显示图标,而 .deb 显示
- python - python中的多处理错误'需要1个位置参数,但给出了2个'