在Java中,能不能把相同的异常处理逻辑统一到一个地方?
In Java, can you consolidate identical exception handling logic to one place?
我正在尝试清理一些 Java 代码。有许多静态工厂方法都执行相同的异常处理。例如,考虑 createA
:
public static A createA() throws XXXX, YYYY {
try {
return somethingThatThrows();
} catch (InterruptedException | ExecutionException e) {
Throwable throwable = e.getCause();
if (throwable instanceOf XXXX) {
throw (XXXX) throwable;
} else if (e instance of YYYY) {
throw (YYYY) throwable;
} else if (throwable != null) {
throw new RuntimeException(throwable);
} else {
throw new RuntimeException(e);
}
}
}
这些 create
方法有很多(每种 returns 一种不同的类型)。对于这些方法中的每一个,都存在此异常处理的副本(即它是重复的)。我希望有一种方法可以避免所有这些相同的代码,并且只在一个地方有这个逻辑。
当然,在没有异常处理的情况下,您只需将逻辑提取到辅助函数中,重复问题就解决了——这个具有异常处理的事实使它与众不同。以下代码 不会 构建:
public static void helper(final Exception e) {
Throwable throwable = e.getCause();
if (throwable instanceOf XXXX) {
throw (XXXX) throwable;
} else if (e instance of YYYY) {
throw (YYYY) throwable;
} else if (throwable != null) {
throw new RuntimeException(throwable);
} else {
throw new RuntimeException(e);
}
}
public static A createA() throws XXXX, YYYY {
try {
return somethingThatThrows();
} catch (InterruptedException | ExecutionException e) {
handle(e);
}
}
有人有什么建议吗?
尝试将公共逻辑提取到私有方法中并调用它:
public static A createA() throws XXXX, YYYY {
try {
return somethingThatThrows();
} catch (InterruptedException | ExecutionException e) {
processInterruptedExcutionExceptions(e);
}
return null;
}
private static void processInterruptedExcutionExceptions(final Exception e) throws XXXX, YYYY {
Throwable throwable = e.getCause();
if (throwable instanceOf XXXX) {
throw (XXXX) throwable;
} else if (e instance of YYYY) {
throw (YYYY) throwable;
} else if (throwable != null) {
throw new RuntimeException(throwable);
} else {
throw new RuntimeException(e);
}
}
这可以通过以下功能性方式处理:
@FunctionalInterface
interface SomethingThatThrows<T> {
T execute() throws XXXX, YYYY, InterruptedException,ExecutionException;
}
private static <T> T handledFuntion(SomethingThatThrows<T> function) throws XXXX, YYYY {
try {
return function.execute();
} catch (InterruptedException | ExecutionException e) {
Throwable throwable = e.getCause();
if (throwable instanceof XXXX) {
throw (XXXX) throwable;
} else if (e instanceof YYYY) {
throw (YYYY) throwable;
} else if (throwable != null) {
throw new RuntimeException(throwable);
} else {
throw new RuntimeException(e);
}
}
}
// Use lambda literal - may be better when arguments are involved
public A createA(String arg1) throws XXXX, YYYY {
return handledFuntion(() -> {
// write code just like you'd write it in try{} body -
// all arguments to createA() are available
return new A(arg1);
});
}
// use a method handle, works best when there are no arguments
public B createB() throws XXXX, YYYY {
return handledFuntion(this::somethingThatMakesB);
}
private B somethingOtherThatMakesB() throws XXXX, YYYY, InterruptedException,ExecutionException {
// Some logic that creates and returns B
}
编辑:合并了@Arkadiy 的回答。
我正在尝试清理一些 Java 代码。有许多静态工厂方法都执行相同的异常处理。例如,考虑 createA
:
public static A createA() throws XXXX, YYYY {
try {
return somethingThatThrows();
} catch (InterruptedException | ExecutionException e) {
Throwable throwable = e.getCause();
if (throwable instanceOf XXXX) {
throw (XXXX) throwable;
} else if (e instance of YYYY) {
throw (YYYY) throwable;
} else if (throwable != null) {
throw new RuntimeException(throwable);
} else {
throw new RuntimeException(e);
}
}
}
这些 create
方法有很多(每种 returns 一种不同的类型)。对于这些方法中的每一个,都存在此异常处理的副本(即它是重复的)。我希望有一种方法可以避免所有这些相同的代码,并且只在一个地方有这个逻辑。
当然,在没有异常处理的情况下,您只需将逻辑提取到辅助函数中,重复问题就解决了——这个具有异常处理的事实使它与众不同。以下代码 不会 构建:
public static void helper(final Exception e) {
Throwable throwable = e.getCause();
if (throwable instanceOf XXXX) {
throw (XXXX) throwable;
} else if (e instance of YYYY) {
throw (YYYY) throwable;
} else if (throwable != null) {
throw new RuntimeException(throwable);
} else {
throw new RuntimeException(e);
}
}
public static A createA() throws XXXX, YYYY {
try {
return somethingThatThrows();
} catch (InterruptedException | ExecutionException e) {
handle(e);
}
}
有人有什么建议吗?
尝试将公共逻辑提取到私有方法中并调用它:
public static A createA() throws XXXX, YYYY {
try {
return somethingThatThrows();
} catch (InterruptedException | ExecutionException e) {
processInterruptedExcutionExceptions(e);
}
return null;
}
private static void processInterruptedExcutionExceptions(final Exception e) throws XXXX, YYYY {
Throwable throwable = e.getCause();
if (throwable instanceOf XXXX) {
throw (XXXX) throwable;
} else if (e instance of YYYY) {
throw (YYYY) throwable;
} else if (throwable != null) {
throw new RuntimeException(throwable);
} else {
throw new RuntimeException(e);
}
}
这可以通过以下功能性方式处理:
@FunctionalInterface
interface SomethingThatThrows<T> {
T execute() throws XXXX, YYYY, InterruptedException,ExecutionException;
}
private static <T> T handledFuntion(SomethingThatThrows<T> function) throws XXXX, YYYY {
try {
return function.execute();
} catch (InterruptedException | ExecutionException e) {
Throwable throwable = e.getCause();
if (throwable instanceof XXXX) {
throw (XXXX) throwable;
} else if (e instanceof YYYY) {
throw (YYYY) throwable;
} else if (throwable != null) {
throw new RuntimeException(throwable);
} else {
throw new RuntimeException(e);
}
}
}
// Use lambda literal - may be better when arguments are involved
public A createA(String arg1) throws XXXX, YYYY {
return handledFuntion(() -> {
// write code just like you'd write it in try{} body -
// all arguments to createA() are available
return new A(arg1);
});
}
// use a method handle, works best when there are no arguments
public B createB() throws XXXX, YYYY {
return handledFuntion(this::somethingThatMakesB);
}
private B somethingOtherThatMakesB() throws XXXX, YYYY, InterruptedException,ExecutionException {
// Some logic that creates and returns B
}
编辑:合并了@Arkadiy 的回答。