一、函数式(Functional)接口
1. 概述
如果一个接口中,只声明了一个抽象方法, 则这个接口就称为函数式接口。
注解:@FunctionalInterface 显式指明改接口是一个函数式接口。可以检验是否是一个函数式接口,同时javadoc也会包含一条声明,说明这个接口是一个函数式接口。
可以通过Lambda表达式创建该接口的对象(若Lambda表达式抛出一个受检异常,即非运行时异常,那么该异常需要在目标接口的抽象方法上进行声明)。
在java.util.function包下定义了java8的丰富的函数式接口。
2. Java内置四大函数式接口
二、方法引用
1. 方法引用
<1> 简介
方法引用,本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例,所以方法引用,也是函数式接口的实例。
方法引用可以看作是Lambda表达式的深层次的表达,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
<2> 使用场景
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用。
<3> 格式
类(对象)::方法名
<4> 情况
1. 对象 :: 实例方法
/**
* 情况1
* 对象 :: 实例方法
* Consumer 中的 void accept(T t)
* PrintStream 中的 void printly(T t)
*/
@Test
public void test1() {
Consumer<String> con1 = str -> System.out.println(str);
con1.accept("北京");
System.out.println("--------------------------");
Consumer<String> con2 = System.out::println;
con2.accept("南京");
}
/**
* 情况1
* 对象 :: 实例方法
* Supplier 中的 T get();
* Employee 中的 String getName()
*/
@Test
public void test2() {
Employee emp = new Employee(1001, "tom", 22, 100.22);
Supplier<String> sup1 = () -> emp.getName();
System.out.println(sup1.get());
System.out.println("--------------------------");
Supplier<String> sup2 = emp::getName;
System.out.println(sup2.get());
}
2. 类 :: 静态方法
/**
* 情况2
* 类 :: 静态方法
* Comparator 中的 int compare(T o1, T o2);
* Integer 中的 int compare(int x, int y)
*/
@Test
public void test3() {
Comparator<Integer> comparator1 = (t1, t2) -> Integer.compare(t1, t2);
System.out.println(comparator1.compare(11112, 123));
System.out.println("--------------------------");
Comparator<Integer> comparator2 = Integer::compare;
System.out.println(comparator2.compare(12, 123));
}
/**
* 情况2
* 类 :: 静态方法
* Function 中的 R apply(T t)
* Math 中的 long round(double a)
*/
@Test
public void test4() {
Function<Double, Long> function1 = d -> Math.round(d);
System.out.println(function1.apply(100.49));
System.out.println("--------------------------");
Function<Double, Long> function2 = Math::round;
System.out.println(function2.apply(101.6));
}
3. 类::实例方法
Lambda 有两个参数, 但方法引用中只有一个参数,其中 Lambda的第一个参数作为调用者
/**
* 情况3
* 类::实例方法
* Lambda 有两个参数, 但方法引用中只有一个参数,其中 Lambda的第一个参数作为调用者
* Comparator 中的 int compare(T o1, T o2);
* String 中的 int t1.compartTo(t2);
*/
@Test
public void test5() {
Comparator<String> comparator1 = (t1, t2) -> t1.compareTo(t2);
System.out.println(comparator1.compare("1233", "1233"));
System.out.println("--------------------------");
Comparator<String> comparator2 = String::compareTo;
System.out.println(comparator2.compare("12332", "1233"));
}
Lambda 有一个参数, 但方法引用中没有参数, Lambda的参数作为调用者
/**
* Lambda 有一个参数, 但方法引用中没有参数, Lambda的参数作为调用者
* Function 中的 R apply(T t)
* Employee 中的 String getName()
*/
@Test
public void test7() {
Employee emp = new Employee(1001, "tom", 22, 100.22);
Function<Employee, String> function1 = e -> e.getName();
System.out.println(function1.apply(emp));
System.out.println("--------------------------");
Function<Employee, String> function2 = Employee::getName;
System.out.println(function2.apply(emp));
}
2. 构造器引用
<1> 无参Lambda ,无参构造器
/**
* 构造器引用 , 无参构造器
* Supplier 中的 T get();
*/
@Test
public void test1() {
Supplier<Employee> supplier1 = () -> new Employee();
Employee employee1 = supplier1.get();
System.out.println(employee1);
System.out.println("--------------------------------------------------------------------");
Supplier<Employee> supplier2 = Employee::new;
Employee employee2 = supplier2.get();
System.out.println(employee2);
}
<2> 一个参数Lambda ,一个参数构造器
/**
* 构造器引用 , 一个参数构造器
* Function 中的 R apply(T t);
*/
@Test
public void test2() {
Function<Integer, Employee> function1 = id -> new Employee(id);
Employee employee1 = function1.apply(2);
System.out.println(employee1);
System.out.println("--------------------------------------------------------------------");
Function<Integer, Employee> function2 = Employee::new;
Employee employee2 = function2.apply(3);
System.out.println(employee2);
}
<3>二个参数Lambda ,二个参数构造器
/**
* 构造器引用 , 二个参数构造器
*/
@Test
public void test3() {
BiFunction<Integer, String, Employee> biFunction1 = (id, name) -> new Employee(id, name);
Employee employee1 = biFunction1.apply(2, "jack");
System.out.println(employee1);
System.out.println("--------------------------------------------------------------------");
BiFunction<Integer, String, Employee> biFunction2 = Employee::new;
Employee employee2 = biFunction2.apply(3, "tom");
System.out.println(employee2);
}
3. 数组引用
数组引用 可以看作是一个特殊的类
/**
* 数组引用
* 数组引用 可以看作是一个特殊的类
* Function 中的 R apply(T t);
*
*/
@Test
public void test4() {
Function<Integer, String[]> function1 = length -> new String[length];
String[] array1 = function1.apply(10);
System.out.println(array1.length);
System.out.println("--------------------------------------------------------------------");
Function<Integer, String[]> function2 = String[]::new;
String[] array2 = function2.apply(13);
System.out.println(array2.length);
}