在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 的回答。