Lambda and Anonymous Classes

  • Lambda 简写的依据java

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

  • Anonymous Classeside

    匿名内部类仍然是一个类,只是不须要程序员显示指定类名,编译器会自动为该类取名。所以若是有以下形式的代码,编译以后将会产生两个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文件分别是主类和匿名内部类产生的:spa

    AnonymousClass.png

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

    // 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 表达式的实现cdn

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

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

    编译以后:blog

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指令进行调用。

相关文章
相关标签/搜索