4

在 Java 中,您不能扩展最终类,但在 Kotlin 中,您可以为此类最终类编写扩展方法。他们是如何让它在内部运作的?我找不到任何解释 Kotlin 扩展方法内部工作原理的文章。

4

2 回答 2

8

在 Java 中,您不能扩展最终类,但在 Kotlin 中,您可以为此类最终类编写扩展方法

我认为您假设扩展方法使用了继承,但事实并非如此。它是一种伪装成 kotlin 语法糖的静态方法。例如看下面的简单扩展方法:

String.removeSpace(): String {
    return this.replace(" ", "")
}

你可以认为它等同于下面的 java 代码。

static String removeSpace(String input) {
    return input.replace(" ", "")
}

kotlin 在这里所做的是它在顶部提供了包装器,以便通过使用this您可以获得调用者的实例。通过将其与 Kotlin 将函数定义为一等公民的能力相结合,您可以编写如下优雅的东西:

fun String.removeSpace() = this.replace(" ", "")
于 2020-08-06T15:04:42.680 回答
4

如果您想知道 Kotlin 代码是如何转换为 Java 代码的,有一种方法可以查看它。IntelliJ 为 Java 代码提供反编译 Kotlin 字节码。你可以找到它Tools -> Kotlin -> Show Kotlin Bytecode并点击它Decompile。然后它将显示 Java 代码。

这是一个例子。

科特林

val Int.asByteArray get() =
    byteArrayOf(
            (this shr 24).toByte(),
            (this shr 16).toByte(),
            (this shr 8).toByte(),
            this.toByte())

val Int.asHex get() = this.asByteArray.asHexUpper

@ExperimentalUnsignedTypes
val ByteArray.asInt get() =
        ((this[0].toUInt() and 0xFFu) shl 24) or
        ((this[1].toUInt() and 0xFFu) shl 16) or
        ((this[2].toUInt() and 0xFFu) shl 8) or
        (this[3].toUInt() and 0xFFu)

爪哇

public final class IntExtensionKt {
   @NotNull
   public static final byte[] getAsByteArray(int $this$asByteArray) {
      return new byte[]{(byte)($this$asByteArray >> 24), (byte)($this$asByteArray >> 16), (byte)($this$asByteArray >> 8), (byte)$this$asByteArray};
   }

   @NotNull
   public static final String getAsHex(int $this$asHex) {
      return HexExtensionKt.getAsHexUpper(getAsByteArray($this$asHex));
   }

   /** @deprecated */
   // $FF: synthetic method
   @ExperimentalUnsignedTypes
   public static void asInt$annotations(byte[] var0) {
   }

   public static final int getAsInt(@NotNull byte[] $this$asInt) {
      Intrinsics.checkParameterIsNotNull($this$asInt, "$this$asInt");
      byte var1 = $this$asInt[0];
      boolean var2 = false;
      int var5 = UInt.constructor-impl(var1);
      short var6 = 255;
      boolean var3 = false;
      var5 = UInt.constructor-impl(var5 & var6);
      byte var7 = 24;
      var3 = false;
      var5 = UInt.constructor-impl(var5 << var7);
      byte var8 = $this$asInt[1];
      var3 = false;
      int var9 = UInt.constructor-impl(var8);
      short var10 = 255;
      boolean var4 = false;
      var9 = UInt.constructor-impl(var9 & var10);
      byte var11 = 16;
      var4 = false;
      var9 = UInt.constructor-impl(var9 << var11);
      var3 = false;
      var5 = UInt.constructor-impl(var5 | var9);
      var8 = $this$asInt[2];
      var3 = false;
      var9 = UInt.constructor-impl(var8);
      var10 = 255;
      var4 = false;
      var9 = UInt.constructor-impl(var9 & var10);
      var11 = 8;
      var4 = false;
      var9 = UInt.constructor-impl(var9 << var11);
      var3 = false;
      var5 = UInt.constructor-impl(var5 | var9);
      var8 = $this$asInt[3];
      var3 = false;
      var9 = UInt.constructor-impl(var8);
      var10 = 255;
      var4 = false;
      var9 = UInt.constructor-impl(var9 & var10);
      var3 = false;
      return UInt.constructor-impl(var5 | var9);
   }
}

如您所见,Kotlin 扩展方法变成了 Java中的public final static方法。final class

于 2020-08-06T17:45:12.157 回答