通过 Java 扩展 Kotlin 类需要我重新实现已经实现的方法

演示该问题的最简单代码是这样的:


Kotlin 中的主界面:


interface Base <T : Any> {

  fun go(field: T)

}

实现它的抽象类和方法:


abstract class Impl : Base<Int> {

  override fun go(field: Int) {}

}

Java类:


public class JavaImpl extends Impl {

}

它应该有效,但事实并非如此。错误是


类&ldquo;JavaImpl&rdquo;必须声明为抽象或在&ldquo;Base&rdquo;中实现抽象方法&ldquo;go(T)&rdquo;


如果 JavaImpl 类在 Kotlin 中,那么它就可以工作。另外,如果T将 投射到String或Integer或任何物体,它也会起作用。但 Int 则不然。


除了使用 Integer 并抑制 Kotlin 子类中的数百个警告之外,还有什么聪明的解决方案吗?


繁华开满天机
浏览 79回答 2
2回答

三国纷争

查看字节码我们可以看到,该类Impl基本上生成了以下函数:public go(I)V其中参数是原始整数。还会生成一个合成桥接函数 ( go(Object)),但它也会在 Java 端针对此类通用函数生成。然而,在 Java 方面,仅仅拥有类似的东西是不够的public void go(int field)。现在我们需要那个go(Integer field)- 函数,但它不存在。kotlin 编译器知道如何处理这个问题,并且不需要在类文件中提供任何有关它的进一步信息(即实现 Kotlin 类知道,它不需要实现类似的东西fun go(field : Int?))。对于 Java 端来说,这样的对应物不存在。我想知道这是否可以通过编译器/字节码很好地解决,或者这是否仍然是一个特定的互操作问题。处理该问题的一些解决方法(如果这是故意的而不是真正的问题):添加一个附加函数如下Impl:fun go(field : Int?) = go(field ?: error("Actually the given field should never be null"))// or simply:fun go(field : Int?) = go(field!!)这样您就不需要实施它。但是,您还会向 Kotlin 端公开该可为 null 的函数,而您可能不希望这样做。出于该特定目的,以相反的方式执行似乎更方便:在 Java 中声明类和接口并在 Kotlin 端使用它。这样你仍然可以声明类似的东西abstract class KotlinClass : JavaInterface<Int> {  override fun go(field : Int) { // an IDE might suggest you to use Int? here...    // ...  }}

慕容3067478

您可以使用它javap来分析问题,显示已编译的接口和类的成员。javap基础public interface Base<T> {&nbsp; public abstract void go(T);}javap 实现public abstract class Impl implements Base<java.lang.Integer> {&nbsp; public void go(int);&nbsp; public void go(java.lang.Object);&nbsp; public Impl();}所以,问题正是@Roland指出的:为了满足接口请求的契约Base,Java编译器需要一个public void go(java.lang.Integer)方法,但Kotlin编译器生成的方法有int作为参数。如果你用 Java 实现接口,比如class JI implements Base<Integer> {&nbsp; &nbsp; @Override&nbsp; &nbsp; public void go(@NotNull Integer field) {&nbsp; &nbsp; }}javap您可以通过获取来分析其编译版本爪哇class JI implements Base<java.lang.Integer> {&nbsp; org.amicofragile.learning.kt.JI();&nbsp; public void go(java.lang.Integer);&nbsp; public void go(java.lang.Object);}因此,如果您打算使用 Kotlin 类Impl作为 Java 类的超类,解决方案就是使用<Integer>,而不是<Int>,作为类型参数:Int是一个 Kotlin 类,int由编译器翻译为;Integer是您通常在 Java 代码中使用的 Java 类。将您的示例更改为abstract class Impl : Base<Integer> {&nbsp; &nbsp; override fun go(field: Integer) {}}public class JavaImpl extends Impl {}JavaJavaImpl类编译时没有错误。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java