A lambda expression is a block of code that you can pass around so it can be executed later.

比如 comparator 或者多线程中的 task,他们仅仅是一小段代码,一个方法足矣,但却因为 Java 的面向对象特征,不得不把一个方法塞进一个类中,并且使用的时候还得实例出来

参数、箭头、内容 () -> {}。参数就像方法的参数那样,内容就像函数体那样

  • 内容如果只有一条语句,可以直接写语句不加 {}
  • 如果参数可被推断,则参数列表中的类型可以不指明 (这涉及到原理,可以往后看)
  • 如果 buff 拉满了,既可被推断,又只有一个参数,那不加 ()
  • 如果内容过长,需要自己写 return。大多数时间,一个表达式返回值是会被推断的

只在 functional interface 中只用 lambda

在 Java 中,lambda 就只在这种情况下使用吧

就算赋值给 Object 也是不允许的

Processing Lambda Expressions

使用 lambda 就是在需要一块过会再执行的代码,以及用在函数接口处

除了 Comparator 之外,还有一些常用的:Predicate, Runnable, Callable

Method References

有时候 lambda 的内容就是调用了一个方法,那这种情况可以用 method references 来处理 (也就是说,当发生仅仅就是调用一个方法的时候,那就考虑转化一下,练多了就会了)

和 lambda expression 的本质一样,都不是 Object,仅仅是编译器处理的一个特例,在面对一个 functional interface 的时候,自动升格为一个对应实例

面对重载的选择

因为函数接口里头只有一个方法签名,会根据这个方法签名的样貌选择合适的方法

Runnable task = System. out:: println;

对于这个样的语句,Runnable 里头是一个 () -> void,所以选择的就是打印空行的方法

有时候一些简单的操作,API 却提供了对应的方法实现,如此脱裤子放屁的行为其实就是为了用在方法引用上,比如 list.removeIf(Objects::isNull);

方法引用和 lambda 大多数时候是一样的

大部份情况,方法引用是 lambda 的一个特例,只有少数情况,比如对 null 指针的错误使用,方法引用会直接报错,而 lambda 毕竟是个函数,要等到真正被调用的时候才会报错

  • object::instanceMethod
  • Class::instanceMethod
  • Class::staticMethod
  • super::instanceMethod
  • this::instanceMethod

Constructor References

Variable Scope

closure (闭包),一个函数会记住他被创建时,可见变量的状态

这也是为什么我一开始没考虑到这个问题,因为我直接默认就看的被创建时的状态。有时候 lambda 会在所在函数结束后,才被调用运行 (比如定时器)

因此,考虑被创建的状态,也就是不能重名了,并且重名也许会调用到意想不到的东西,比如 this

不可捕获的情况

书中有简单的提到,可以理解为当 lambda 被创建时,那些可见的变量会被记录在自己的字段中,这一听就知道这个字段不能被修改吧

  • lambda 内不能修改。毕竟 lambda 生效的时候,函数可能都已经结束了
  • lambda 外不能修改,同理

More about Comparators