• lambda与匿名内部类


    lambda与匿名内部类

    当lambda表达式中引用到this,指示的是外部类的引用这个时候编译器会创建匿名内部方法,并且在程序运行期间动态的并加载内部类,可以使用java -Djdk.internal.lambda.dumpProxyClasses class文件名 来将运行时的的内部类的字节码输出对应的class文件。若是lambda没有使用外部类的引用filed等相关就创建静态内部方法。而匿名内部类的方式则是在javac编译时直接生成对应的内部类class字节码,并且创建相应的示例。

    kotlin local function个人简介

    private fun test() {
        val a: (Int) -> Unit = {
        }
        a(2)
    }
    
    private fun test1() {
        fun a(a: Int) {
        }
    
        a(2)
    }
    
    

    这两种方式都使用了本地函数,但它是如何实现的呢?我们看一下kotln的字节码

    private final static test()V
       L0
        LINENUMBER 2 L0
        GETSTATIC LambdaAndLocalFunKt$test$a$1.INSTANCE : LLambdaAndLocalFunKt$test$a$1;
        CHECKCAST kotlin/jvm/functions/Function1
        ASTORE 0
       L1
        LINENUMBER 4 L1
        ALOAD 0
        ICONST_2
        INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
        INVOKEINTERFACE kotlin/jvm/functions/Function1.invoke (Ljava/lang/Object;)Ljava/lang/Object; (itf)
        POP
       L2
        LINENUMBER 5 L2
        RETURN
       L3
        LOCALVARIABLE a Lkotlin/jvm/functions/Function1; L1 L3 0
        MAXSTACK = 2
        MAXLOCALS = 1
        
        
     ==================================================================================================
     final class LambdaAndLocalFunKt$test$a$1 
     				extends kotlin/jvm/internal/Lambda 
     							implements kotlin/jvm/functions/Function1 {
     	public final static LLambdaAndLocalFunKt$test$a$1; INSTANCE
     	
     	 // access flags 0x1041
      public synthetic bridge invoke(Ljava/lang/Object;)Ljava/lang/Object;
        ALOAD 0
        ALOAD 1
        CHECKCAST java/lang/Number
        INVOKEVIRTUAL java/lang/Number.intValue ()I
        INVOKEVIRTUAL LambdaAndLocalFunKt$test$a$1.invoke (I)V
        GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
        ARETURN
        MAXSTACK = 2
        MAXLOCALS = 2
        
        
     	public final invoke(I)V
        // annotable parameter count: 1 (visible)
        // annotable parameter count: 1 (invisible)
       L0
        LINENUMBER 3 L0
        RETURN
       L1
        LOCALVARIABLE this LLambdaAndLocalFunKt$test$a$1; L0 L1 0
        LOCALVARIABLE it I L0 L1 1
        MAXSTACK = 0
        MAXLOCALS = 2
     
     }
    
    

    test()跟test1()大同小异我们只对其中之一test()进行分析
    image-20210510223438752

    调用类的invoke(object)方法,在该方法中调用invoke(Int)方法。

    我们来考虑在方法中持有外部局部变量的情况

    private fun test() {
        val s = 2
        val a: (Int) -> Unit = {
            println(it)
            println(s)
        }
        a(2)
    }
    
     private final static test()V
       L0
        LINENUMBER 2 L0
        ICONST_2
        ISTORE 0
       L1
        LINENUMBER 3 L1
        NEW LambdaAndLocalFunKt$test$a$1
        DUP
        ILOAD 0
        INVOKESPECIAL LambdaAndLocalFunKt$test$a$1.<init> (I)V
        CHECKCAST kotlin/jvm/functions/Function1
        ASTORE 1
    

    我们只关注重点代码

    这次不同的是要使用new创建对象并且调用init()方法对对象进行初始化,我们来观察一下对象的初始化。

     <init>(I)V
        ALOAD 0
        ILOAD 1
        PUTFIELD LambdaAndLocalFunKt$test$a$1.$s : I
        ALOAD 0
        ICONST_1
        INVOKESPECIAL kotlin/jvm/internal/Lambda.<init> (I)V
        RETURN
        MAXSTACK = 2
        MAXLOCALS = 2
    
      // access flags 0x1010
      final synthetic I $s
    

    很明显他会将其以final的形式将引用到的外部对象保存起来。

  • 相关阅读:
    CDH5.13 集成Kerberos配置
    使用bash脚本删除文件最后几行
    yolov3模型微调(fine-tune)备忘
    ubuntu 18.04 rsync 命令使用 服务端配置
    python 子包调用 跨目录调用
    [转]命令行界面 (CLI)、终端 (Terminal)、Shell、TTY的联系与区别
    bash shell 判断变量是否在列表中
    TensorFlow 图像分类模型 inception_resnet_v2 模型导出、冻结与使用
    numpy 数组集合运算及下标操作
    Win10 Service'MongoDB Server' failed to start. Verify that you have sufficient privileges to start system services【简记】
  • 原文地址:https://www.cnblogs.com/FCY-LearningNotes/p/14799792.html
Copyright © 2020-2023  润新知