Kotlin 扩展函数实现原理分析

673 阅读2分钟
原文链接: www.jianshu.com

Kotlin 扩展函数实现原理分析

Kotlin 的扩展函数非常的方便好用,支持给现有的java类增加函数,代码如下:

fun String.hello(world : String) : String {
    return "hello " + world + this.length;
}
fun main(args: Array<String>) {
    System.out.println("abc".hello("world"));
    // 打印 hello world3
}

动机

我们就可以调用所有的 String 类型的 hello 方法,Kotlin 这么做的动机就是位替代我们的各种 Utils:FileUtils、StringUtils 等。

作用范围

大多数时候我们在顶层定义扩展,即直接在包里。

原理分析

我们可以通过编写的 Kotlin 代码反编译看看到底是怎么做到的。

  • 首先通过 Android Studio 自带的工具查看字节码 搜索 Kotlin ByteCode
  • 然后在生成字节码点击反编译 如图操作就可以看到我们想看的代码了

    通过反编译的代码可以看出,其实 Kotlin 的扩展函数并没有修改原有的 String 类,而是在自己的类中生成了一个静态的方法,当我们在 Kotlin 中调用扩展函数时,编译器将会调用自动生成的函数并且把当前的对象(String)传入。
package com.antonioleiva.weatherapp;

import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {1, 1, 15},
   bv = {1, 0, 3},
   k = 2,
   d1 = {"\u0000\u0014\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0011\n\u0002\u0010\u000e\n\u0002\b\u0004\u001a\u0019\u0010\u0000\u001a\u00020\u00012\f\u0010\u0002\u001a\b\u0012\u0004\u0012\u00020\u00040\u0003¢\u0006\u0002\u0010\u0005\u001a\u0012\u0010\u0006\u001a\u00020\u0004*\u00020\u00042\u0006\u0010\u0007\u001a\u00020\u0004¨\u0006\b"},
   d2 = {"main", "", "args", "", "", "([Ljava/lang/String;)V", "hello", "world", "app_debug"}
)
public final class ExtensionKt {
   @NotNull
   public static final String hello(@NotNull String $this$hello, @NotNull String world) {
      Intrinsics.checkParameterIsNotNull($this$hello, "$this$hello");
      Intrinsics.checkParameterIsNotNull(world, "world");
      return "hello " + world + $this$hello.length();
   }

   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      System.out.println(hello("abc", "world"));
   }
}