认识lambda表达式
学习背景:
我是在学习线程的时候,第一次遇见了lambda表达式,当时对于这个知识点还非常的陌生,应该说是从来没见过。于是乎,为了充实自己的之时,我去学习了lambda表达式。
我们先来看一下lambda表达式到底长什么样子
- 当然,对于我这个小白来说,学习的时候我得先知道这个洋气的东西叫啥呀,一个英语单词,但是不会读。学习的时候,在视频里,我知道搞了半天,这个东西就是数学里常用到的λ。当时的我感到无比的…
- 举个栗子:
()->{System.out.println("msn")}
没错,这个东西就是一个lambda表达式,我相信,大家差不多能猜到这句代码是什么意思,就是让控制台输出‘msn’三个字母。
那么,我们通过对这个代码的解释,来了解如何书写lambda表达式
- 首先,我们要知道什么样的代码才可以使用lambda表达式来化简代码
- 其次,要知道lambda表达式的书写形式及其解释
lambda表达式的使用情况
- 一个接口,而且这个接口中只有一个抽象方法,我们可以使用lambda表达式对抽象方法进行重写。比如线程中Runnable接口需要作为Thread的参数时。
通常情况下,我们需要实现Runnable接口重写run方法,然后创建此实现类的对象,将此对象作为参数传递给Thread;或者使用匿名内部类的方法重写run方法。但是,以上过程可以通过lambda表达式的方式进行代码的简化。
lambda表达式具体实现
- 范式:
(parameter list)->{code block}
- 说明:
-
parameter list:参数列表。内容是接口中的抽象方法的参数。如果没有参数就空着。参数需要加类型。java11后,参数可以是var类型的。
-
->:固定写法:相当于表示这一串代码是lambda表达式,这个符号也是意味着指向下面的代码块
-
code block:代码块。我们在抽象方法中具体要执行的代码
- 注意:lambda表达式中的变量有一些要求,必须是final或者effective final的。
Local variable a defined in an enclosing scope must be final or effectively final
这句话是什么意思呢?
final自然不用多说了,就是常量的意思。code block中可以使用常量。effective final呢?实际的常量,有效的常量,其实就是说,当我们在lambda外定义了一个并不是final修饰的变量,但是这个变量的值赋值一次后并没有发生过改变,则编译器会把这个变量当作一个常量来处理。
也即是下面几种情况:
1.定义了一个变量,但是没有赋值,在lambda中不可以使用
2.定义了一个变量,并且赋值一次,在lambda中可以使用
3.lambda外定义了一个变量,并且多次赋值,或者进行过++,--
等改变值的操作,在lambda不可以使用
4.在lambda中定义了一个变量,可以进行数值的操作,lambda可以正常使用
5.定义的final 变量,自然可以使用
- 注意:lambda表达式中的变量有一些要求,必须是final或者effective final的。
-
lambda表达式的缺省规则
- 当满足特定的条件时,lambda表达式可以省略
- 可以省略参数的类型。如果有多个参数,不能只省略一个,必须全部省略
- 如果只有一个参数,可以省略参数的小括号
- 如果代码块只有一条语句:
如果没有返回值,可以将大括号和代码后的分号省略
如果有返回值,在省略大括号和分号后,需要将return省略
- 当满足特定的条件时,lambda表达式可以省略
-
lambda表达式注意事项
- 必须要有接口,接口中只能有一个方法
- 必须要有上下文环境
-
当我们使用lambda表达式时,只提供了参数和方法体,所以单独写lambda表达式是不知道实现了哪个类的哪个方法的。又由于lambda表达式中只有一个抽象方法,所以只要提供他是属于哪一个接口的就可以。
- 因此,使用时,要么使用lambda给一个对象赋值。
Runnable r=()->{Syste.out.rintln("aa");}
- 要么作为参数,而且这个方法的参数是可以根据方法唯一确定的。
new Thread(()->{...})
- 或者作为函数的返回值。因为返回值的类型也是确定的。
- 或者作为数组的元素。同理
- 因此,使用时,要么使用lambda给一个对象赋值。
-
总之,lambda表达式相当于实现了对象接口并创建了其对象的意思。对象能做的,lambda表达式都可以做。
-
lambda表达式中使用this
因为静态方法中不能使用this,所以要使用lambda表达式中使用this,一定是在一个非静态方法中,而非静态方法的this就是当前对象,所以lambda的this就是当前对象。lambda表达式不开辟新的作用域。与匿名内部类不同。因为使用匿名内部类时也需要new 一个对象,自然this指的是new 的新对象啦