2017-08-24 90 views
7

我在科特林定义的函数:如何声明一个函数参数来接受抛出的函数?

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

当我编译我得到这个错误:

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

如何定义我的函数参数以接受抛出的函数?

+0

您可以尝试注释您的convertExceptionToEmpty函数以抛出IOException,这可能会绕过此错误。 – Piwo

+0

@piwo,我认为这不会有帮助,异常来自''getStaticWidgets()''方法 –

回答

4

的问题是,Java有checked exceptions但科特林没有。 requestFunc参数类型() -> List<Widget>将映射到功能接口Function0<List<Widget>>,但运算符invoke不会在Kotlin代码中引发检查异常。

所以你不能在lambda表达式中调用getStaticWidgets(),因为它会抛出一个IOException,这是一个Java中检查的异常。

由于您同时控制科特林和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); 
0

恐怕没有什么可以做,但捕获了异常:

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

     return null; 
    }); 
相关问题