【问题标题】:How to implement this Java interface in Kotlin?如何在 Kotlin 中实现这个 Java 接口?
【发布时间】:2017-10-23 06:35:35
【问题描述】:

既然 Kotlin 没有原语,那么如何实现这个接口呢?

public interface A {
  @NotNull Object get(@NotNull Integer i);
  @NotNull Object get(int i);
}

我无法更改 Java 代码,因为它是二进制库中的已编译类文件。

【问题讨论】:

  • fun get(i: Integer /* or Integer? */) = ...; fun get(i: Int) = ... 有什么问题?

标签: java kotlin kotlin-interop


【解决方案1】:

如果单个实现(如@zsmb13 的答案)对您来说还不够,并且您需要在 Kotlin 中为这两个方法分别实现,那么您可以添加一个中间接口,覆盖接受 Integer 的方法可空参数:

private interface IntermediateA : A {
    override fun get(i: Int?): Any
}

实现这个接口而不是原来的A,Kotlin 编译器会区分这两种方法,允许你重写它们如下:

class C : IntermediateA {
    override fun get(i: Int) = "primitive"
    override fun get(i: Int?) = "boxed"
}

val a: A = C()
println(a.get(1)) // primitive
println(a.get(1 as Int?)) // boxed

如果您可以访问 Java 代码,则可以通过向接受装箱类型的方法添加可空性注释来解决此问题:

Object get(@Nullable Integer i);

Kotlin 编译器理解不同类型的可空性注解,here's the list

【讨论】:

    【解决方案2】:

    只实现一个以Int 作为参数的方法是可行的,并且可以从 Kotlin 或 Java 中调用。

    class B : A {
    
        override fun get(i: Int): Any {
            return "something"
        }
    
    }
    

    如果您反编译字节码,您会发现 Kotlin 编译器足够聪明,可以创建这两种方法,其中一种只是重定向到真正的实现。

    一个可能的问题是,您不能使该方法采用Int?,如果像这样从Java 调用它,它会在.intValue() 调用上因NullPointerException 而崩溃:

    B b = new B();
    Integer i = null;
    b.get(i);
    

    我不确定是否有解决该用例的方法。

    编辑:热键的答案包含其余的答案。

    【讨论】:

    • 如果我有两个完全不同的实现,具体取决于它是int 还是Integer?如何在 Kotlin 中获得这种差异化?
    • 在这种情况下似乎不可能。通常,您可以通过声明一个采用 Int 处理原语的方法和另一个采用 Int? 处理装箱类型的方法来区分这些。
    • 好的,我明白你的意思了。但是我不明白为什么盒装的不会立即发送到Int,只要它的值是notnull
    • 有办法,但是需要Java方法参数注解为@Nullable。由于无法访问 Java 代码,似乎只能使用中间 Java 接口,请参阅另一个答案。
    • 其实一个Kotlin中间接口就够了(只覆盖一个Int?参数类型的函数)。
    【解决方案3】:

    在 Kotlin 中,我们可以声明:

    • 原始 int as : Int
    • 盒装 int as : Int?

    你的界面可以简化为:

    private interface ModifiedA : A {
        override fun get(i: Int?): Any
    }
    

    在 Kotlin 中,如果您实现了这个修改后的接口,那么 Kotlin 将为您提供两种方法来覆盖。一种用于原始类型,另一种用于盒装类型。

    class ImplementationOfA : ModifiedA {
        override fun get(i: Int)
        override fun get(i: Int?)
    }
    

    【讨论】:

      【解决方案4】:

      我用 Java 写了一个简单的演示。

      然后在 IntelliJ IDEA 或 Android Studio 中使用 Kotlin 插件将其转换为 Kotlin。

      【讨论】:

        【解决方案5】:

        在 kotlin 中添加这些行来实现接口

        class abc : AppCompatActivity(), interface 1, interface 2,
        {
        override fun get(i: Int?): Any
        }
        

        【讨论】:

        • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
        • AppCompatActivity 的相关性如何?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-12
        • 2021-01-29
        • 1970-01-01
        • 2017-12-30
        • 1970-01-01
        • 2018-01-29
        • 2016-06-08
        相关资源
        最近更新 更多