2017-07-07 41 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

用完整的堆棧跟蹤進行更新。 –