Java lambda 你了解多少

最近在编写一些Java业务,使用了 Lambda语法,所以有必要整理一下lambda相关的知识,以便能够加深理解。

  • 什么是lambda表达式?
  • lambda语法格式
  • lambda 表达式重要特征
  • 函数式接口
  • lambda使用
  • 匿名类和lambda中this指针
  • 参考网站

1、什么是lambda表达式?

Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。

2、lambda语法格式

(parameters) -> expression

(parameters) -> {expression;}

3、lambda 表达式重要特征

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

4、函数式接口

  • 什么是函数式接口:

    • 函数式接口(Functional Interface)是Java 8对一类特殊类型的接口的称呼。 这类接口只定义了唯一的抽象方法的接口(除了隐含的Object对象的公共方法), 因此最开始也就做SAM类型的接口(Single Abstract Method)。
    • 函数式接口中可以额外定义Object中多个抽象方法,但这些抽象方法签名必须和Object的 public 方法一样
  • Java8新增函数式接口

    • Predicate -- 传入一个参数,返回一个bool结果, 方法为boolean test(T t)
    • Consumer -- 传入一个参数,无返回值,纯消费。 方法为void accept(T t)
    • Function -- 传入一个参数,返回一个结果,方法为R apply(T t)
    • Supplier -- 无参数传入,返回一个结果,方法为T get()
    • UnaryOperator -- 一元操作符,继承Function,传入参数的类型和返回类型相同。
    • BinaryOperator -- 二元操作符, 传入的两个参数的类型和返回类型相同, 继承BiFunction

5、lambda使用

  • 循环打印List中的值
  • 老方法:for(Integer i: list) { System.out.println(i);}
  • Lambda表达式:list.forEach(x->System.out.println(x));
public static void main(String... args) {
    List list = Arrays.asList(10, 5, 4, 1, 76);

    for(Integer i: list) {
        System.out.println(i);
    }

    list.forEach(x -> System.out.println(x));
}

-反编译代码


for:
45: aload_1
46: invokeinterface #5,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/I
terator;
51: astore_2
52: aload_2
53: invokeinterface #6,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
58: ifeq          81
61: aload_2
62: invokeinterface #7,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/O
bject;
67: checkcast     #2                  // class java/lang/Integer
70: astore_3
71: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
74: aload_3
75: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/Object;
)V
78: goto          52



lambda:
81: aload_1
82: invokedynamic #10,  0             // InvokeDynamic #0:accept:()Ljava/util/function/Consumer
;
87: invokeinterface #11,  2           // InterfaceMethod java/util/List.forEach:(Ljava/util/fun
ction/Consumer;)V


private static void lambda$main$0(java.lang.Integer);
    Code:
       0: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: aload_0
       4: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/Object;
)V
       7: return

  • lambda 编译的时候生成了一个动态方法,调用也是执行命令invokedynamic

6、匿名类和lambda中this指针

  • 示例代码
public void test1(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println(this.toString());
        }
    }).start();

    new Thread(()->System.out.println(this.toString())).start();
}

  • 反编译
public class com.yuxiu.test.Main {

    public void test1();
        Code:
           0: new           #5                  // class java/lang/Thread
           3: dup
           4: new           #6                  // class com/yuxiu/test/Main$1
           7: dup
           8: aload_0
           9: invokespecial #7                  // Method com/yuxiu/test/Main$1."":(Lcom/yuxiu/test
    /Main;)V
          12: invokespecial #8                  // Method java/lang/Thread."":(Ljava/lang/Runnable;
    )V
          15: invokevirtual #9                  // Method java/lang/Thread.start:()V
          18: new           #5                  // class java/lang/Thread
          21: dup
          22: aload_0
          23: invokedynamic #10,  0             // InvokeDynamic #0:run:(Lcom/yuxiu/test/Main;)Ljava/lang
    /Runnable;
          28: invokespecial #8                  // Method java/lang/Thread."":(Ljava/lang/Runnable;
    )V
          31: invokevirtual #9                  // Method java/lang/Thread.start:()V
          34: return
    
    
    private void lambda$test1$0();
        Code:
           0: getstatic     #11                 // Field java/lang/System.out:Ljava/io/PrintStream;
           3: aload_0
           4: invokevirtual #12                 // Method java/lang/Object.toString:()Ljava/lang/String;
           7: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;
        )V
          10: return
}

  • 结论:
    • 匿名类this指向匿名类

    • lambda中this指向lambda外的类

7、参考网站

  • http://www.runoob.com/java/java8-lambda-expressions.html

  • http://colobu.com/2014/10/28/secrets-of-java-8-functional-interface/

  • http://blog.oneapm.com/apm-tech/226.html

你可能感兴趣的:(Java lambda 你了解多少)