![](/img/trans.png)
[英]Can we pass java method to to kotlin function of type () -> Unit?
[英]Can I override kotlin method which returns Unit type in Java
主要问题:如何在返回 Unit 类型的 java 中覆盖 kotlin 方法?
我正在尝试在 java 中使用 kotlin 库,并且有一个名为override fun invoke(): Unit
我必须实现的方法。
但是,java 编译器一直告诉我return type void is not compatible with Unit
。
我试过public Unit invoke() { return Unit.INSTANCE; }
public Unit invoke() { return Unit.INSTANCE; }
在 java 但发生编译错误。
invoke()' in 'myproject' clashes with 'invoke()' in 'library';
attempting to use incompatible return type
kotlin 接口(在库中)
interface MessageHandler<M : Message> : (Message) -> Unit {
override fun invoke(message: Message): Unit =
if (messageType.isAssignableFrom(message.javaClass)) {
println("invoked ${message.javaClass.simpleName}")
} else {
throw IllegalArgumentException("Unsupported message type ${message.javaClass.simpleName}")
}
}
java 抽象 class (在我的项目中)
public abstract class AbstractMessageHandler<T extends Message> implements MessageHandler<T> {
@Override
public void invoke(@NotNull Message message) {
//this is where the compile error occurs.
}
}
错误信息
(Message) in AbstractMessageHandler cannot implement invoke(P1) in Function1
public void invoke(@NotNull Message message) {
^
return type void is not compatible with Unit
where P1,R are type-variables:
P1 extends Object declared in interface Function1
R extends Object declared in interface Function1
看起来像一个 4 年前未解决的错误: https://youtrack.jetbrains.com/issue/KT-15964
引:
由于与旧二进制文件的兼容性,我认为现在不可能。 我们会看看我们能做些什么,谢谢你的报告。
一个丑陋的解决方法是使用可空类型
Unit?
:interface TestA<out T> { fun foo(): T } abstract class TestB: TestA<Unit?> { override fun foo(): Unit? { //... return Unit } }
有了这个,您将不需要在 Java 子类中覆盖
foo
。 如果你想覆盖它,Java 子类中的签名应该是public Unit foo()
。
如果你不控制图书馆,我不确定你能做什么。
从java.util.function.Consumer
继承:
interface MessageHandler<M: Message>: Consumer<Message> { override fun accept(message: Message): Unit = if (messageType.isAssignableFrom(message.javaClass)) { println("invoked ${message.javaClass.simpleName}") } else { throw IllegalArgumentException("Unsupported message type ${message.javaClass.simpleName}") } }
或者使用Any
代替Unit
并在 Java 代码中返回null
:
interface MessageHandler<M: Message>: (Message) -> Any { override fun accept(message: Message): Any = if (messageType.isAssignableFrom(message.javaClass)) { println("invoked ${message.javaClass.simpleName}") } else { throw IllegalArgumentException("Unsupported message type ${message.javaClass.simpleName}") } }
如果不能,我认为最好,如果可能的话,在 Kotlin 中编写AbstractMessageHandler
及其所有子类:
abstract class AbstractMessageHandler: MessageHandler<Message> { override fun invoke(message: Message) { //... } }
但是,如果您不调用默认MessageHandler.invoke
并且您的代码与MessageHandler
类型无关,您可以简单地从java.util.function.Consumer
继承:
public class AbstractMessageHandler implements Consumer<Message> { @Override public void accept(Message message) { //... } }
只是在错误之前提一下:
(Message) in AbstractMessageHandler cannot implement invoke(P1) in Function1
...
您应该会看到如下内容:
'invoke(Message)' in '...MessageHandler' clashes with 'invoke(P1)' in
'kotlin.jvm.functions.Function1'; attempting to use incompatible return type
因为 Java 编译器看到两个接口,一个来自(Message) -> Unit
:
public interface kotlin.jvm.functions.Function1 {
Object invoke(Messsage var1);
}
另一个来自MessageHandler
:
public interface MessageHandler extends Function1 {
void invoke(@NotNull Message var1);
}
// (Some details were ommitted for simplicity)
这在 Java 中是不可能的,因为MessageHandler.invoke
尝试使用不同的返回类型覆盖Function1.invoke
,如jls-8.4.8.3中所述,
如果具有返回类型 R1 的方法声明 d1 覆盖或隐藏具有返回类型 R2 的另一个方法 d2 的声明,则 d1 必须是 d2 的返回类型可替换( 第 8.4.5 节),否则会发生编译时错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.