Intereting Posts
Android kotlin переопределяет методы интерфейса внутри метода onCreateView () Котлин: лямбда никогда не компилируется В Kotlin, как я идиоматически обращаюсь к значениям вложенной карты с нулевым значением или возвращать значение по умолчанию? Встроенный сеттер или Нет для создания неиспользуемого сеттера в Котлине? Какова концепция намерения Котлина? Блокировка serialVersionUID в Котлине Android Kotlin onItemSelectedListener для неработающего счетчика Firebase Android – создайте пользователя с помощью электронной почты и пароль в Kotlin Настроить автоматическое завершение IntelliJ для сценария градиента в kotlin Быстрое наследование объектов и значение интерфейса Использование префикса «m» для переменных в Котлине Как отобразить частичный экран камеры в kotlin (Java + Kotlin) Autowiring: ожидается не менее 1 бит, который квалифицируется как кандидат на автоподключение для этой зависимости Определение общих свойств без наследования Java vs Kotlin – методы Spring @Async в одном классе

Интерфейс Java SAM, созданный из Kotlin, дает ClassCastException

У меня есть метод java:

addHandler(HttpServiceHandler handler) 

HttpServiceHandler

 interface HttpServiceHandler extends Consumer<HttpHandlerContext> 

Суть заключается в том, чтобы избежать Consumer<HttpHandlerContext> copy-paste в проекте, поэтому это своего рода псевдоним типа.

В коде Java это работает правильно:

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

Теперь, в Kotlin, у меня есть этот метод, который генерирует обработчики:

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

HttpServiceHandler {} важен, он не компилируется, если я не 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)) 

И я понятия не имею, почему.

Update2: тестовый код на странице https://github.com/wilem82/testcases/tree/master/kotlinsam1 . К сожалению, это не повторяет проблему.

ошибка уже говорила точно:

java.lang.ClassCastException: blah.BlahTest $ Companion $ newHandler $ 1 не может быть добавлен в kotlin.jvm.functions.Function.1

вы пытаетесь Consumer<HttpHandlerContext> в Function1 в методе addHandler или где-нибудь, например:

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

вы должны использовать выражение ссылки метода в java / function reference expression в kotlin для преобразования интерфейса SAM в другой интерфейс SAM, например:

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

Если вы вызываете java-метод addHandler в kotlin, вам не нужно создавать такой метод-мост newHandler , вы можете просто называть его лямбдой в kotlin, например:

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