重学Kotlin之局部函数

576 阅读1分钟

局部函数

所谓局部函数就是在函数内部定义函数

关于java

java显然在语法上是不支持的. 这样的代码显然是会报错的.

public class Test {
    public static void main(String[] args) {

        public void doSome () {
            System.out.println("This is a local method");
        }

        doSome();

    }
}

关于Kotlin

kotlin显然是支持这样的写法的.

fun main() {
    fun localFunction() {
        println("I am local function")
    }

    localFunction()

}

实现原理

秉承着知其然知其所以然,很有必要知道这样一个方便的语法特性是如何是如何实现的. 打开show kotlin bytecode插件decompile ohh~ 好像看不懂

public final class LocalFunctionKt {
    public static final void main() {
      <undefinedtype > $fun$localFunction$1 = null.INSTANCE;
        $fun$localFunction$1.invoke();
    }

    // $FF: synthetic method
    public static void main(String[] var0) {
        main();
    }
}

考虑看看有咩有额外的的class生成, 经分析后发现显然没有

img2.png

接着分析字节码 img_1.png

{
  public static final void main();
    descriptor: ()V
    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=0, locals=0, args_size=0
         0: invokestatic  #9                  // Method main$localFunction:()V
         3: return

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x1009) ACC_PUBLIC, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=0, locals=1, args_size=1
         0: invokestatic  #12                 // Method main:()V
         3: return
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       4     0  args   [Ljava/lang/String;

  private static final void main$localFunction();
    descriptor: ()V
    flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL
    Code:
      stack=2, locals=0, args_size=0
         0: ldc           #16                 // String I am local function
         2: getstatic     #22                 // Field java/lang/System.out:Ljava/io/PrintStream;
         5: swap
         6: invokevirtual #28                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
         9: return
      LineNumberTable:
        line 3: 0
        line 4: 9
}

代码等价于

public final class LocalFunctionKt {
    public static final void main() {
        main$localFunction();
    }

    public static void main(String[] args) {
        main();
    }

    private static final void main$localFunction() {
        System.out.println("I am local function");
    }
}
  • 所以kotlin的局部函数其实也就是普通的函数
  • 编译以后是同级的
  • 其实现原理也就是通过编译器静态检查从而实现所谓的局部