lambda表达式
lambda表达式就是函数传递。核心思想是:以参数的形式去实现函数式接口,说直白点就是要实现的接口的实现代码可以直接写在参数中。和匿名内部类非常像,功能也一样。对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。这种接口称为函数式接口(functional interface)。
lambda与匿名内部类不同的地方在于以下3条特性:
1:不用"new Object(){.....}"而是直接传递代码块。
2:可以有多个默认实现方法,但声明式方法只允许有一个,否则变不能称之为函数式接口。
3:懒加载,当创建对象的代码不会执行,当需要这个对象的时候才会执行创建对象的代码。
下面是一个很简单的demo:通过demo可以验证上面的结论,当stu1,stu2调用test方法时输出的内容为:“stu1 -> i`m the code to execute~~~“,“stu2 -> i`m the code to execute~~~”,之所以在调用test方法的时候才输出原因是当真正创建的时候才会执行lambda的内容。属于懒加载。
如果设计你自己的接口,其中只有一个抽象方法,可以用@FunctionalInterface注解来标记这个接口。这样做有两个优点。如果你无意中增加了另一个非抽象方法,编译器会产生一个错误消息。另外javadoc页里会指出你的接口是一个函数式接口。并不是必须使用注解。根据定义,任何有一个抽象方法的接口都是函数式接口。不过使用@FunctionalInterface注解确实是一个很好的做法。
package cn.mr.li.test; public class Test { public static void main(String[] args) throws InterruptedException { Student stu1 = i -> System.out.println("stu1 -> i`m the code to execute~~~"); stu1.test("Be substitute!!!"); Student stu2 = i -> { System.out.println("stu2 -> i`m the code to execute~~~"); }; stu2.test("Be substitute!!!"); //输出结果: //stu1 -> i`m the code to execute~~~ //stu2 -> i`m the code to execute~~~ } } package cn.mr.li.test;
@FunctionalInterface public interface Student { void test(Object object); // void aaa(String name, int age); //不能出现第二个声明式方法,否则就不能算是函数式接口。 default void test() { System.out.println("这是函数式接口中被实现的方法,可以存在"); } }
java核心技术卷一中提到:
使用lambda表达式的重点是延迟执行(deferred execution)。毕竟,如果想要立即执行代码,完全可以直接执行,而无需把它包装在一个lambda表达式中。之所以希望以后再执行代码,这有很多原因,如:·在一个单独的线程中运行代码;·多次运行代码;·在算法的适当位置运行代码(例如,排序中的比较操作);·发生某种情况时执行代码(如,点击了一个按钮,数据到达,等等);·只在必要时才运行代码。
常用函数式接口
基本类型的函数式接口
注:p,q为int,long,double;P,Q为Int,Long,Double