Как объявить параметр функции, чтобы принимать функции, которые бросают?

Я определил функцию в Котлине:

fun convertExceptionToEmpty(requestFunc: () -> List<Widget>): Stream<Widget> {
    try {
        return requestFunc().stream()
    } catch (th: Throwable) {
        // Log the exception...
        return Stream.empty()
    }
}

Я определил метод Java с этой подписью:

List<Widget> getStaticWidgets() throws IOException;

Я пытаюсь составить их так:

Stream<Widget> widgets = convertExceptionToEmpty(() ->  getStaticWidgets())

Когда я компилирую, я получаю эту ошибку:

Ошибка: (ln, col) java: незарегистрированное исключение java.io.IOException; должен быть пойман или объявлен брошенным

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


person Michael Richardson    schedule 24.08.2017    source источник
comment
Вы можете попробовать аннотировать свою функцию convertExceptionToEmpty, чтобы генерировать исключение IOException, которое могло бы обойти эту ошибку.   -  person Piwo    schedule 24.08.2017
comment
@piwo, я не думаю, что это поможет, исключение исходит от метода getStaticWidgets()   -  person Schidu Luca    schedule 24.08.2017


Ответы (2)


Проблема в том, что в Java есть проверенные исключения, а в Kotlin — нет. Тип параметра requestFunc () -> List<Widget> будет сопоставлен с функциональным интерфейсом Function0‹List‹Widget>>, но оператор invoke не генерирует проверенное исключение в коде Kotlin.

Таким образом, вы не можете вызвать getStaticWidgets() в лямбда-выражении, поскольку оно выдает IOException, которое является проверенным исключением в Java.

Поскольку вы управляете как кодом Kotlin, так и кодом Java, самое простое решение — изменить тип параметра () -> List<Widget> на Callable<List<Widget>>, например:

// change the parameter type to `Callable` ---v
fun convertExceptionToEmpty(requestFunc: Callable<List<Widget>>): Stream<Widget> {
    try {
        //                 v--- get the `List<Widget>` from `Callable`
        return requestFunc.call().stream()
    } catch (th: Throwable) {
        return Stream.empty()
    }
}

Затем вы можете использовать выражение ссылки на метод в Java8, например:

Stream<Widget> widgets = convertExceptionToEmpty(this::getStaticWidgets);

//OR if `getStaticWidgets` is static `T` is the class belong to
//                                               v
Stream<Widget> widgets = convertExceptionToEmpty(T::getStaticWidgets);
person holi-java    schedule 24.08.2017

Боюсь, вы ничего не можете сделать, кроме как поймать это исключение:

 Stream<Integer> widgets = convertExceptionToEmpty(() -> {
        try {
            return getStaticWidgets();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    });
person Schidu Luca    schedule 24.08.2017