如何在用 Kotlin 编写的接口中使用 Java 8 默认方法的特性

Aji*_*a S 2 java interface java-8 kotlin default-method

我在 Java 中有一个类 A,在 Kotlin 中有一个接口 B。

// kotlin
interface B {
    fun optional()
}
Run Code Online (Sandbox Code Playgroud)
// java
class A implements B {
}
Run Code Online (Sandbox Code Playgroud)

我想在 Kotlin 接口 (B) 中编写默认方法(Java 8 特性),并想在类 A 中实现它,我该如何实现?

提前致谢。

Ily*_*lya 5

在 Kotlin 中,带有主体的接口方法默认编译如下:

// kotlin
interface B {
    fun optional() { println("B optional body") }
}
Run Code Online (Sandbox Code Playgroud)

大致编译为:

public interface B {
   void optional();
   public static final class DefaultImpls {
      public static void optional(B $this) {
         System.out.println("B optional body");
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

然后,在实现此接口的 Kotlin 类中,编译器会optional自动为方法添加覆盖并调用B.DefaultImpls.optional(this)那里。

public final class KA implements B {
   public void optional() {
      B.DefaultImpls.optional(this);
   }
}
Run Code Online (Sandbox Code Playgroud)

但是如果你想在 Java 中实现这个接口并且避免必须覆盖optional方法和B.DefaultImpls手动调用怎么办?在这种情况下,您可以使用实验@JvmDefault功能

首先,您需要启用几个编译器选项:

  • JVM 目标字节码版本 1.8 或更高版本: -jvm-target 1.8
  • 启用 JVM 默认方法:(-Xjvm-default=enable通过上面的链接查看其他可用的选项值)

然后,您使用注释对optional方法进行@JvmDefault注释:

// kotlin
interface B {
    @JvmDefault
    fun optional() { println("B optional body") }
}
Run Code Online (Sandbox Code Playgroud)

它被编译为

// kotlin
interface B {
    @JvmDefault
    fun optional() { println("B optional body") }
}
Run Code Online (Sandbox Code Playgroud)

现在这个接口的 Java 实现变成了:

public interface B {
   @JvmDefault
   default void optional() {
      System.out.println("B optional body");
   }
}
Run Code Online (Sandbox Code Playgroud)