行为参数化,是将方法作为参数进行传递,可以适应更多的需求变化。
行为参数化中的方法参数,在JDK8之前可以使用匿名累来进行传递,也可以通过一个指定接口实现一个类来进行传递。
总之,行为参数化传递代码有助于应对不断变化的需求。
可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
Lambda表达式可以作为参数传递给方法或者存储在变量中。
Lambda表达式分为三部分、
1.参数列表。传递给Lambda的主体
2.箭头。用于把参数列表和Lambda主体隔开。
3.Lambda主体。表达式就是Lambda的返回值。可以使void、String等等类型。
Lambda示例
布尔表达式List
创建对象() -> new Apple(10)
消费一个对象
(Apple a) -> { System.out.println(a.getWeight()); }
从一个对象中选择/抽取(String s) -> s.length()
组合两个值(int a, int b) -> a * b
比较两个对象的值(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())
Lambda引用的外部变量必须是不可修改的,被final修饰的。
函数式接口就是只定义一个抽象方法的接口。并且它可以有1个或者多个默认方法。
public interface Predicate{ boolean test (T t); }
函数描述符是什么?也就是函数的抽象方法。例如Runnable接口,它就是() -> void。
注解@FunctionalInterface
这个标注用于表示该接口会设计成一个函数式接口。如果不符合要求,编译器会返回错误。
任何函数式接口都不允许抛出受检异常。
如果需要抛出异常:1.可以定义接口时声明抛出受检异常。2.可以把lambda包在try/catch块中。
特殊void兼容逻辑:如果Lambda主体是一个语句表达式,那它一个返回void的函数描述符兼容。
Lambda表达式不能操作外部局部变量,因为java中局部变量是存在每个线程的栈中。Lambda相当于另一个线程!
1.java.util.function.Predicate
java.util.function.Predicate接口定义了一个名叫test的抽象方法,它接受泛型 T对象,并返回一个boolean。
2.java.util.function.Consumer
java.util.function.Consumer
定义了一个名叫accept的抽象方法,它接受泛型T 的对象,没有返回(void)。你如果需要访问类型T的对象,并对其执行某些操作(打印、处理数据),就可以使用这个接口。
3.java.util.function.Function
java.util.function.Function
接口定义了一个叫作apply的方法,它接受一个 泛型T的对象,并返回一个泛型R的对象。如果你需要定义一个Lambda,将输入对象的信息映射到输出,就可以使用这个接口
类型检查过程:
检查方法接口定义、检查定义类型、检查入参类型(接收什么返回什么)
可以用在静态方法、实例方法、某个对象的实例方法。
Lambda操作构造函数
Supplier c1 = () -> new Apple(); Apple a1 = c1.get(); //简化 Supplier c2 = Apple::new; Apple a2 = c2.get(); Function f1 = (weight) -> new Apple(weight); Apple a3 = f1.apply(200); //简化 Function f2 = Apple::new; Apple a4 = f2.apply(100);
1.Predicate谓词
注意优先级是从左到右的~
2.Function函数
Function接口为此配 了andThen和compose两个默认方法。
同样也可以自己实现
这种复杂Lambda也能实现