Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I declare a function parameter to accept functions that throw?

I have defined a function in Kotlin:

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

I have defined a Java method with this signature:

List<Widget> getStaticWidgets() throws IOException;

I attempt to compose them like so:

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

When I compile I get this error:

Error:(ln, col) java: unreported exception java.io.IOException; must be caught or declared to be thrown

How do I define my function parameters to accept a function that throws?

like image 347
Michael Richardson Avatar asked Aug 24 '17 14:08

Michael Richardson


People also ask

Can you put a function in a parameter?

A function can take parameters which are just values you supply to the function so that the function can do something utilising those values. These parameters are just like variables except that the values of these variables are defined when we call the function and are not assigned values within the function itself.

How do parameters and functions work together?

When a function is called, all of the parameters of the function are created as variables, and the value of each of the arguments is copied into the matching parameter. This process is called pass by value.

What is function parameter C++?

Parameters and Arguments Information can be passed to functions as a parameter. Parameters act as variables inside the function. Parameters are specified after the function name, inside the parentheses.

How can you get the type of arguments passed to a function?

There are two ways to pass arguments to a function: by reference or by value. Modifying an argument that's passed by reference is reflected globally, but modifying an argument that's passed by value is reflected only inside the function.


1 Answers

The problem is that Java has checked exceptions but Kotlin does not. The requestFunc parameter type () -> List<Widget> will be mapped to the functional interface Function0<List<Widget>> but the operator invoke doesn't throw a checked exception in Kotlin code.

So you can't call the getStaticWidgets() in lambda expression since it throws a IOException which is a checked exception in Java.

Since you control both the Kotlin and Java code, the simplest solution is to change the parameter type () -> List<Widget> to Callable<List<Widget>>, for example:

// 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()
    }
}

Then you can use Method Reference Expression in Java8 as further, for example:

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

//OR if `getStaticWidgets` is static `T` is the class belong to
//                                               v
Stream<Widget> widgets = convertExceptionToEmpty(T::getStaticWidgets);
like image 51
holi-java Avatar answered Oct 03 '22 13:10

holi-java