2017-07-07 52 views
1

我有一个Java方法:从科特林创建的Java SAM界面给人ClassCastException异常

addHandler(HttpServiceHandler handler) 

HttpServiceHandler

interface HttpServiceHandler extends Consumer<HttpHandlerContext> 

的一点是要避免在项目Consumer<HttpHandlerContext>复制粘贴,所以它是一种一个类型别名。

在Java代码中,这个工程的所有权利:现在

addHandler({ context -> context.blah(); }) 

,在科特林,我有这种方法生成的处理程序:

private companion object { 
    fun newHandler(notimportant: Long): HttpServiceHandler { 
     return HttpServiceHandler { context -> context.blah() } 
    } 
} 

HttpServiceHandler {}是很重要的,它并不如编译我没有为lambda指定HttpServiceHandler

这编译:

addHandler(newHandler(1L)) 

但在运行时,会抛出:

java.lang.ClassCastException: blah.BlahTest$Companion$newHandler$1 cannot be cast to kotlin.jvm.functions.Function1 

at blah.BlahTest.test(BlahTest.kt:42) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:498) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) 
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) 
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) 

而且我想不通为什么。请帮助?

更新:,如果我把它写这样的类转换异常消失:

addHandler(
    object : HttpServiceHandler { 
     override fun accept(c: HttpHandlerContext) { 
      c.complete() 
     } 
    } 
) 

但仍然抛出的时候这样写的除外:

fun newHandler(blah: Long): HttpServiceHandler { 
    return object : HttpServiceHandler { 
     override fun accept(c: HttpHandlerContext) { 
      c.complete() 
     } 
    } 
} 

addHandler(newHandler(1L)) 

而且我也没办法为什么。

更新2:测试代码在https://github.com/wilem82/testcases/tree/master/kotlinsam1。不幸的是,这并不能重现问题。

+0

无法重现。发布一个完整的重现问题的最小例子。 –

+0

@JBNizet确认,它不会在干净的测试项目中重现。猜猜我会把它移到Kotlin论坛。 –

+0

增加了关于什么代码能够工作的信息,以防有人根据这些信息判断发生了什么。 –

回答

1

误差已经精确地说:

java.lang.ClassCastException:blah.BlahTest $伴侣$ newHandler $ 1不能被转换为kotlin.jvm.functions。功能1

您尝试投下Consumer<HttpHandlerContext>Function1addHandler法或其他地方,例如:

fun addHandler(handler: Consumer<HttpHandlerContext>) { 
    val it: Function1<*, *> = handler as Function1<*, *> 
    //      ^
    // ClassCastException was thrown since it is not a Function1 
} 

你应该使用方法参照表达在Java /函数参考表达科特林转换一个SAM接口到另一个SAM接口,例如:

fun addHandler(handler: Consumer<HttpHandlerContext>) { 
    val it: Function1<HttpHandlerContext, Unit> = handler::accept 
    //  using function reference expression here  ---^ 
    //... 
} 

IF你打电话JAV在科特林方法addHandler,你不必创建这样一个桥法newHandler,你可以使用拉姆达叫它科特林,例如:

addHandler{context-> 
    context.blah() 
    // additional works ... 
} 
+0

没有明确的转换任何东西给'Function1'。 java方法需要'HttpServiceHandler',我给它'HttpServiceHandler {c - > c.blah()}'。添加了一个说明代码的github项目。可悲的是,这个问题并没有在测试中重现。 –

+0

@YuriGeinish嗨,你需要给你的问题整个stacktrace。 :),你不能重现问题,也许你没有清理你的项目。在哪里有相同的功能'addHandler'。 –

+0

用完整的堆栈跟踪进行更新。 –