Java 8 - бросить несколько общих проверенных исключений в лямбда

В проекте, над которым я работаю, я нашел класс, который обертывает все методы своего суперкласса в некоторой сложной обработке исключений. Он выглядит примерно так:

public void method1() throws ExceptionA {
    String exceptionString = "";
    try {
        super.method1();
    } catch (ExceptionA e) {
         exceptionString = // <convert the exception to string in an elaborate way>
         throw e;
    } finally {
         // <an elaborate logger call which uses value of exceptionString>
    }
}

public void method2() throws ExceptionB, ExceptionC {
    String exceptionString = "";
    try {
        super.method2();
    } catch (ExceptionB | ExceptionC e) {
         exceptionString = // <convert the exception to string in elaborate way>
         throw e;
    } finally {
         // <an elaborate logger call which uses value of exceptionString>
    }
}

// ... <a bunch of other methods like this>

Я сразу же сказал: «Вау, как могло бы быть одна универсальная обертка и просто называть ее в каждом из этих методов. Класс был бы как на 10х короче!». Так что я должен работать.

Здесь я застрял:

private interface ThrowingMethod<E extends Exception> {
    void run() throws E;
}

public <E extends Exception> void wrapMethod(ThrowingMethod<E> method) throws E {
    String exceptionString = "";
    try {
        method.run();
    } catch (Exception e) {
         exceptionString = // <convert the exception to string in an elaborate way>
         throw e;
    } finally {
         // <an elaborate logger call which uses value of exceptionString>
    }
}

public void method1() throws ExceptionA {
    wrapMethod(super::method1); // works
}

public void method2() throws ExceptionB, ExceptionC {
    wrapMethod(super::method2); // Error in Eclipse: "Unhandled exception type Exception"
}

// ... <a bunch of other methods like this>

В заключение этот подход работает для методов, которые генерируют только один тип проверенных исключений. Когда метод выбрасывает несколько проверенных исключений, Java предполагает, что тип исключения - это Exception .

Я попытался добавить более общие параметры в ThrowingMethod и wrapMethod но это ничего не меняет.

Как я могу получить функциональный интерфейс для работы с несколькими генерическими исключениями?

Всего 2 ответа


Когда вы расширяете свой интерфейс для использования двух переменных типа, т.е.

private static interface ThrowingMethod<E1 extends Exception,E2 extends Exception> {
    void run() throws E1, E2;
}

public <E1 extends Exception,E2 extends Exception>
void wrapMethod(ThrowingMethod<E1,E2> method) throws E1,E2 {
    // same as before
}

правила относительно вывода типа не изменяются, и они одинаковы для обеих переменных типа. Например, вы все еще можете использовать

public void method1() throws ExceptionA {
    wrapMethod(super::method1);
}

как и раньше, поскольку компилятор просто вводит один и тот же единственный тип исключения для обеих переменных типа.

Для метода, объявляющего два исключения, он не будет выбирать один для переменной первого типа, а второй для второго; нет правила, которое могло бы сообщить компилятору, какое исключение использовать для переменной типа.

Но вы можете помочь компилятору в этом случае, например

public void method2() throws ExceptionB, ExceptionC {
    wrapMethod((ThrowingMethod<ExceptionB, ExceptionC>)super::method2);
}

который лучше всего подходит для этого подхода.


Таким образом, ваша цель состоит в том, чтобы обернуть кучу методов с протоколированием? Типичным способом справиться с этим является АОП . Вы просто создали бы единственный pointcut, который соответствует всем этим методам, и у вас не будет куча повторяющегося шаблона. Нет необходимости в этих интерфейсах или методах упаковки.


Есть идеи?

10000