Lambda
Lambda表达式是一个匿名函数,其本质是匿名方法,即当我们编译程序时,编译器会自动将,将表达式转换为”匿名方法”。
Lambda表达式是java8的重要更新,它支持将代码块作为方法参数,允许使用更加简洁的代码来创建只有一个抽象方法的接口,这种接口称为函数式接口。
有两种方式:使用匿名内部类来实现方法并调用 和 使用Lambda表达式来实现方法并调用。
区别:
1、不需要new…( )这种繁琐的代码。
2、不需要指出重写方法的名字。
3、不需要给出重写方法的返回类型。
4、只需要给出重写方法的括号以及括号里的形参列表。
由此总结Lambda表达式的组成部分:
1、形参列表:允许省略形参类型;如果形参列表中只有一个参数,甚至连圆括号都可以省略。
2、箭头:->
3、代码块:如果代码块中只包含一条语句,Lambda代码块允许省略花括号;如果只有一条return语句甚至可以省略return 关键字;如果该Lambda表达式需要返回值,并且代码块只有一条省略了return 的语句(实际上就不能有return),就会自动返回这条语句的值;如果参数要加修饰符或者标签,参数必须加上完整类型。
注意:在Lambda表达式调用方法时,本应该传入的是接口的对象,但实际上传入的是Lambda表达式,Lambda表达式会被当成一个”任意类型”的对象,那么到底需要当成何种类型的对象,这取决于运行环境的需要。
Lambda表达式中的变量:
1、参数:
2、局部变量:
3、自由变量(final):不用担心线程问题
结论:lambda表达式的自由变量会被保存,无论什么时候都会执行lambda,都可以直接使用,并且自由变量不能被修改。(操作自由变量的代码块,称为闭包)。
Lambda表达式的类型,也被称为”目标类型”,Lambda表达式的目标类型必须是”函数式接口”。函数式接口是只包含一个抽象方法的接口,可以包含多个默认方法、类方法。如Runnable、Comparator等接口都是函数式接口。
Lambda表达式有两个限制:
1、目标类型必须是明确的函数式接口。
2、只能实现一个方法。
当Lambda表达式实现的匿名方法与目标类型中唯一的抽象方法有相同的形参列表,同样的Lambda表达式就可以被当成不同的目标类型。例如:Runnable和FkTest接口的Lambda表达式通用(表达式里都不含参)。
Java8在java.until.function包下预定义了很多函数式接口,典型包含这4类:
1、XxxFunction:apply( ),该方法对参数进行处理、转换,返回一个新的值。
2、XxxConsumer:accept( ):和apply( )一样,只是不返回处理结果。
3、XxxPredicate:test( ),对参数进行某种判断,返回boolean值。经常用于进行筛滤数据。
4、XxxSupplier:getAsXxx( ),不需要输入参数,会按某种逻辑算法返回一个数据。
Lambda表达式和匿名内部类:
联系:都可以直接访问”effectively final”(局部内部类和匿名内部类访问的局部变量必须由final修饰,java8开始,可以不加final修饰符的局部变量。)的局部变量,以及外部类的成员变量。都可以直接调用从接口中继承的默认方法(java8可以在接口中写入成员方法,加default)。
区别:匿名内部类可以为任意的接口创建实例,只要实现所有抽象方法即可,但Lambda表达式只能为函数式接口创建实例。匿名内部类可以为抽象类甚至普通类创建实例。匿名内部类实现的抽象方法允许调用接口体允许调用接口中定义的默认方法,但Lambda表达式的代码块不允许调用接口中定义的默认方法。