Lambda and Anonymous Classes

  • Lambda 简写的依据

    能够使用 Lambda 的依据是必须有相应的函数接口(函数接口,是指内部只有一个抽象方法的接口),也就是说你并不能在代码的任何地方任性的写Lambda表达式。Lambda表达式另一个依据是类型推断机制(在上下文信息足够的情况下,编译器可以推断出参数表的类型,而不需要显式指名)

  • Anonymous Classes

    匿名内部类仍然是一个类,只是不需要程序员显示指定类名,编译器会自动为该类取名。因此如果有如下形式的代码,编译之后将会产生两个class文件:

    public class MainAnonymousClass {
    	public static void main(String[] args) {
    		new Thread(new Runnable(){
    			@Override
    			public void run(){
    				System.out.println("Anonymous Class Thread run()");
    			}
    		}).start();;
    	}
    }
    

    编译之后文件分布如下,两个class文件分别是主类和匿名内部类产生的:

    AnonymousClass.png

    进一步分析主类MainAnonymousClass.class的字节码,可发现其创建了匿名内部类的对象:

    // javap -c MainAnonymousClass.class
    public class MainAnonymousClass {
      ...
      public static void main(java.lang.String[]);
        Code:
           0: new           #2                  // class java/lang/Thread
           3: dup
           4: new           #3                  // class MainAnonymousClass$1 /*创建内部类对象*/
           7: dup
           8: invokespecial #4                  // Method MainAnonymousClass$1."<init>":()V
          11: invokespecial #5                  // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
          14: invokevirtual #6                  // Method java/lang/Thread.start:()V
          17: return
    }
    
  • Lambda 表达式的实现

    Lambda 表达式通过 invokedynamic 指令实现,书写 Lambda 表达式不会产生新的类。

    public class MainLambda {
    	public static void main(String[] args) {
    		new Thread(
    				() -> System.out.println("Lambda Thread run()")
    			).start();;
    	}
    }
    

    编译之后:

Lambda

通过javap反编译命名,我们更能看出Lambda表达式内部表示的不同:

// javap -c -p MainLambda.class
public class MainLambda {
  ...
  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/Thread
       3: dup
       4: invokedynamic #3,  0              // InvokeDynamic #0:run:()Ljava/lang/Runnable; /*使用invokedynamic指令调用*/
       9: invokespecial #4                  // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
      12: invokevirtual #5                  // Method java/lang/Thread.start:()V
      15: return

  private static void lambda$main$0();  /*Lambda表达式被封装成主类的私有方法*/
    Code:
       0: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #7                  // String Lambda Thread run()
       5: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

反编译之后我们发现Lambda表达式被封装成了主类的一个私有方法,并通过invokedynamic指令进行调用。

https://juejin.im/post/5c3a10c451882524830b0612

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值