Lambda表达式
匿名内部类 => lambda
匿名内部类:
Thread myThread = new Thread(new Runnable() { public void run() { System.out.println("匿名内部类"); } });
lambda表达式:
Thread myThread = new Thread(() -> System.out.println("Lambda表达式"));
语法糖:
JDK7以前,在匿名内部类中访问局部变量时,需要使用final修饰访问的局部变量
jdk8时,匿名内部类和lambda表达式访问的局部变量可以不用final修饰,但是局部变量默认为final变量
基础语法
语法格式1)
无参数,无返回值
() -> System.out.println(“hello world”)
语法格式2)
只有一个参数,无返回值
(x) -> System.out.println(x)
语法格式3)
若只有一个参数,()可以不写
x -> System.out.println(x)
语法格式4)
多个参数,多条语句,并有返回值
Comparator<Integer> com = (x,y) -> { System.out.println(“函数式接口”); return Integer.compare(x,y); };
语法格式5)
若lambda体中只有一条语句,return和{}都可以省略不写
Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
语法格式6)
lambda的参数列表的数据类型可以省略不写,因为JVM编译器根据上下文推断出数据类型,即”类型推断”
四大内置核心函数式接口
Consumer<T> :消费型接口
void accept(T t)
Supplier<T> :供给型接口
T get()
Function<T, R> : 函数型接口
R apply(T t)
Predicate<T> : 断言型接口
boolean test(T t)
方法引用和构造器引用
方法引用:
语法格式:
对象::实例方法名
PrintStream ps = System.out; Consumer<String> con = x -> ps.println(x); con.accept("lambda表达式");
Consumer<String> con2 = ps::println;
con2.accept("对象名::实例方法名");
类::静态方法名
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
Comparator<Integer> com = Integer::compare;
类::实例方法名
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
BiPredicate<String, String> bp2 = String::equals;
注意:
Lambda调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致
若Lambda参数列表中的第一参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用类名::实例方法名的方式
构造器引用:
语法格式:
类名::new
Supplier<Student> sup = () -> new Student();
Supplier<Student> sup = Student::new;
注意:
所使用的构造器方法是由接口抽象方法参数列表决定的
函数式接口@FunctionalInterface
特点:
1) 该注解只能标记在”有且只有一个抽象方法”的接口上
2) JDK8接口中的静态方法和默认方法,都不算抽象方法
3) 接口默认继承java.lang.Object,如果接口显示声明覆盖了Object中的方法,也不算抽象方法
4) 该注解不是必须的,如果一个接口符合”函数式接口”定义,那么加不加注解都没有影响