java - 在构造函数中使用多捕获异常类型
问题描述
假设我需要结合 2 个 api,它们基本上在每个方法上都会抛出异常。代码通常看起来像这样混乱:
class MultiApi{
Api1 api1;
Api2 api2;
//I led the caller handle problems
Api2Data doSomethingOrThrow() throws Api1Ex, Api2Ex {
byte[] data = api1.getData();
return api2.handleData(data);
}
//I try to recover
Api2Data somethingElse(){
try{
byte[] data = api1.getData();
return api2.handleData(data);
catch (Api1Ex e){ // handle
} catch (Api2Ex e) //handle
}
// if not handled
return null;
}
}
所以我想我可以像这样写一个 ExceptionWrapper:
class Wrapper extends Exception{
private Exception mTrigger;
public Wrapper(Api1Ex e) {
mTrigger = e;
}
public Wrapper(Api2Ex e) {
mTrigger = e;
}
public int getCode(){
if (mTrigger instanceof Api1Ex) {
return ((Api1Ex)mTrigger).getCode();
} else {
return ((Api2Ex)mTrigger).getCode();
}
}
}
并像这样使用它:
Api2Data doSomethingOrThrow() throws Wrapper {
try{
byte[] data = api1.getData();
return api2.handleData(data);
catch (Api1Ex | Api2ex e){
throw new Wrapper(e);
]
}
但是 Java 抱怨它无法解析类型。我也无法在构造函数中使用简洁的多捕获语法:
Wrapper(Api1Ex | Api2Ex e){
mTrigger = e;
}
所以我需要写这样的东西:
Wrapper(Exception e){
if (e instanceof Api1Ex || e instanceof Api2Ex) {
mTrigger = e;
} else {
throw new RuntimeException("Got unkown Ex type!");
}
}
从我的角度来看,这非常丑陋。这个问题有更好(意味着更优雅)的解决方案吗?我通常不感兴趣,哪个 Api 失败,只有其中一个失败,以及它抛出了哪个 errorCode(在两种情况下都具有相同的含义)
我有点想到鸭子打字功能:任何带有 a 的异常getCode
就足够了。
编辑:
许多人建议最简单的方法是实现一个通用类型。但我无法以任何方式或形式修改 Api1 或 Api2。此外,getCode
它不返回一个 int,而是一个包含一个 int 的枚举。枚举类型(当然)不一样,但它们的int
表示是一样的。
解决方案
如果要使用多捕获块,则需要一个采用and的最小上限 ( LUB ) 类型的构造函数。Api1Ex
Api1Ex
异常参数的声明类型,表示它的类型是与替代的
D1 | D2 | ... | Dn
联合lub(D1, D2, ..., Dn)
。https://docs.oracle.com/javase/specs/jls/se12/html/jls-14.html#jls-14.20
没有其他办法了。构造函数Wrapper(Api1Ex | Api2Ex e)
永远无效。
如果您声明了几个 catch 块,重载的构造函数将起作用。
try {
...
} catch(Api1Ex exception) {
throw new Wrapper(exception);
} catch (Api2Ex exception) {
throw new Wrapper(exception);
}
在某些时候,您需要在同时使用异常的部分和仅处理包装器异常的部分之间划清界限。那条线可能看起来很难看(就像上面的片段),但至少,它会帮助你减少所有地方的“丑陋”。
推荐阅读
- parallel-processing - 在并行编程中,只划分一个等于可用处理器的问题有意义吗?
- python - 将列中的值转置到列标题?
- azure - 关于调用一个实体的多个编排功能的问题
- matlab - 使用 imagesc 使网格可见(Linux 软件 opengl)
- swift - 带有 Xcode 12 的 Interface Builder 文件中的未知类 QuoteDetailViewController
- python - 如何在 Jupyter Notebook 中运行使用 txt 文件的 py 文件
- .net-core - 使用 System.Diagnostic 中的 activitySource 时如何关闭自动 Request-Context httpHeader
- java - What is the best way to add small numbers to the corner of each cell in a table or grid?
- amazon-web-services - GuardDuty 和 Custodian 阻止 IP
- javascript - 如何将下拉值添加到数据库并在 javascript 中使用它?