• 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的形式将引用到的外部对象保存起来。

  • 相关阅读:
    C++ | 继承(基类,父类,超类),(派生类,子类)
    C++ std::pair的用法
    派生类构造函数和多重继承的二义性问题
    C++vector and opencv Mat
    C++中union的使用方法
    C++中数组作为形参的方法
    在Python中使用OpenCV(CV2)对图像进行边缘检测
    你可能会用到的一些小程序效果、工具
    AI口算批改、练习小程序
    拍照搜题小程序
  • 原文地址:https://www.cnblogs.com/FCY-LearningNotes/p/14799792.html
Copyright © 2020-2023  润新知