Lambda表达式
-- 本质上就是一个匿名方法.(未命名的方法)
# 该方法不是独立执行的
# 用于实现由函数式接口定义的另一个方法
# Lambda表达式会导致产生一个匿名类.
# Lambda表达式也成为闭包.
什么是函数式接口?
只含有一个抽象方法的接口,只有一个方法的接口
比如 : Runnable,它只定义了一个run()方法.
操作符 ' ->' 它将Lambda表达式分成两个部分.
左边 -> 右边 | 参数 -> 方法
左边 : 需要的所有参数(如果不需要,则使用空的参数列表)
右边 : Lambda体(Lambda要执行的动作)
Java定义了两种Lambda体
1. 包含单独一个表达式
2. 包含一个代码块
例子 :
public interface MyNumber { double getValue(); } MyNumber myNumber = () -> 123.45; // !注意 : 要使用Lambda表达式,那么该抽象方法的类型和Lambda表达式的类型必须兼容
泛型函数式接口
Lambda表达式自身不能指定类型参数,所以,Lambda表达式不能是泛型,但是与Lambda表达式关联的函数市接口可以是泛型.
Lambda 中可以访问外部作用域定义的变量.
1. Lamdba可以使用外部定义的变量(包括 this 变量),但是不能改变他的值.只能使用
int index = 0; () -> { // ... // index++; // error, 不能改变外部不同变量的值 // 我可以在这里面使用 index 变量,但是不能修改它的值. }
为什么在Lambda中不能改变外部定义的变量?
因为对于Lambda来说,外部定义的普通变量,都是 final 修饰过的变量,虽然它们并没有真正使用 final 修饰,但是对于Lambda来说,就是这样,所有在Lambda中不能修改外部定义的普通变量,因为 final 修饰过的变量一旦被复制,是不能够被修改的.
2. Lamdba可以使用外部定义的静态(static)变量,并且可以改变他的值.
static index = 0; () -> { // ... // index++; // OK, 我可以改变它的值,因为它是一个静态变量. // 我可以在这里面使用 index 变量,并且可以改变它的值. }
方法引用
方法引用提供了一种引用而不执行方法的方式.
因为Lambda需要由兼容的函数式接口构成的目标类型上下文,计算时,方法引用也会创建函数式接口的一个实例.
1. 静态方法的方法引用
语法 :
ClassNama::methodName
类名 :: 方法名
实例 :
interface MyFace(){ String myFaceFunction(String str); } class MyTest{ String myTestFunction(String str){ return str + "helloworld"; } } ... public static void main(String args[]){ // 当然这个接口必须是一个函数式接口 ( 也就是该接口有且只有一个方法 ) // 并且这个接口中的方法 返回类型,参数 必须和 引用的方法 返回类型,参数一致 // 注意 : 引用的方法必须是静态方法. // 接口 = 类名::方法名 MyFace face = MyTest::myTestFunction; // 这样这个接口有得到了一个引用,然后就可以使用接口中的方法了. face.myFaceFunction("helloworld!"); }
2. 实例方法的方法引用
语法 :
objectReference::methodName
静态方法的方法引用 与 实例方法的方法引用 比较
// 1. 静态 MyFace face = MyTest::myTestFunction; // ClassNama::methodName // 要求 : MyTest对象中的方法必须'是 ' static 的(当然方法返回,参数等等要与接口中的一致) // 2. 实例 MyTest test = new MyTest(); MyFace face = test::myTestFunction; // objectReference::methodName // 要求 : MyTest对象中的方法必须'不是' static 的