方法引用
当要传递给Lambda体
的操作已经有实现的方法时就可以使用方法引用,方法引用和构造器引用就是为了简化Lambda表达式
语法糖(Syntactic sugar)
也译为糖衣语法是指计算机语言中添加的某种对语言的功能没有影响但是更方便程序员使用的语法
方法引用格式: 使用方法引用操作符 “::
” 将类或对象
与方法名
分隔开来,要求Lambda体只有一句语句并且是调用一个对象/类的方法
引用的方法的形参和返回值
和函数式接口抽象方法的形参和返回值
都相同,所以引用方法的形参可以省略
对象::实例方法名
类::静态方法名
类::实例方法名
先写一个Employee
实体类
public class Employee {
private String name;
private Integer id;
// get和set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
// 构造方法
public Employee() {
}
public Employee(Integer id) {
this.id = id;
this.name = name;
}
public Employee(Integer id,String name) {
this.id = id;
this.name = name;
}
}
**对象::非静态方法
:接口抽象方法a在被重写
时使用了某一个对象的方法b,如果方法a和b的形参列表,返回值类型都相同
,则可以使用方法b实现对方法a的重写替换 **
@Test
public void test() {
// 使用Lambda表达式
Consumer<String> consumer01 = s -> System.out.println(s);
consumer01.accept("她的手只有我的手四分之三那麼大");
System.out.println("-----------------------------");
// 使用方法引用
//PrintStream printStream = System.out;
//Consumer consumer02 = printStream::println;
Consumer<String> consumer02 = System.out::println;
consumer02.accept("可我還是沒能抓住");
}
@Test
public void test() {
Employee emp = new Employee(1001,"Tom");
// 使用Lambda表达式
Supplier<String> sup1 = () -> emp.getName();
System.out.println(sup1.get());
System.out.println("*******************");
// 使用方法引用
Supplier<String> sup2 = emp::getName;
System.out.println(sup2.get());
}
类::静态方法
: :接口抽象方法a在被重写
时使用了某一个类的静态方法b,如果方法a和b的形参列表,返回值类型都相同
,则可以使用方法b实现对方法a的重写替换
@Test
public void test07() {
// 使用Lambda表达式
Comparator<Integer> comparator01 = (o1, o2) -> Integer.compare(o1, o2);
System.out.println(comparator01.compare(20, 77));
System.out.println("----------------------------");
// 使用方法引用
Comparator<Integer> comparator02 = Integer::compare;
System.out.println(comparator02.compare(94, 21));
}
@Test
public void test08(){
// 使用Lambda表达式
Function<Double,Long> function01 = aDouble -> Math.round(aDouble);
System.out.println(function01.apply(3.141));
System.out.println("------------------------------");
// 使用方法引用
Function<Double,Long> function02 = Math::round;
System.out.println(function02.apply(2.717));
}
类::实例方法
: 抽象方法a在被重写
时使用了某一个对象的方法b,如果方法a和b的返回值类型相同但方法b的形参少一个
,则可以使用方法b实现对方法a的重写替换
@Test
public void test5() {
// 使用Lambda表达式
Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
System.out.println(com1.compare("abc","abd"));
System.out.println("*******************");
// 使用方法引用
Comparator<String> com2 = String :: compareTo;
System.out.println(com2.compare("abd","abm"));
}
@Test
public void test10(){
// 使用Lambda表达式
BiPredicate<String,String> biPredicate01 = (o1, o2) -> o1.equals(o2);
System.out.println(biPredicate01.test("Kyle", "Kyle"));// true
System.out.println("----------------------------------");
// 使用方法引用
BiPredicate<String,String> biPredicate02 = String::equals;
System.out.println(biPredicate02.test("Violet", "Violet"));// true
}
@Test
public void test7() {
Employee employee = new Employee(1001, "Jerry");
// 使用Lambda表达式
Function<Employee,String> func1 = e -> e.getName();
System.out.println(func1.apply(employee));
System.out.println("*******************");
// 使用方法引用
Function<Employee,String> func2 = Employee::getName;
System.out.println(func2.apply(employee));
}
@Test
public void test11(){
Ememployee employee = new Employee(1001, "Jerry");
Function<Stu,String> function01 = employee -> employee.toString();
System.out.println(function01.apply(employee));
System.out.println("------------------------------");
Function<Employee,String> function02 = Employee::toString;
System.out.println(function02.apply(employee employee));
}
构造器引用
类名::new
: 要求Lambda体只有一句语句并且是用来创建一个对象,构造方法的形参列表和返回值(构造器对应类的对象)要与接口中抽象方法一致才可以替换
Supplier中的T get()和Employee的无参构造方法Employee()
Function中的R apply(T t)和Employee的有参构造方法Employee(id)
BiFunction中的R apply(T t,U u)和Employee的有参构造方法Employee(id,name)
@Test
public void test1(){
// 传统写法
Supplier<Employee> sup = new Supplier<Employee>() {
@Override
public Employee get() {
return new Employee();
}
};
System.out.println("*******************");
// Lambda表达式
Supplier<Employee> sup1 = () -> new Employee();
System.out.println(sup1.get());
System.out.println("*******************");
// 构造器引用
Supplier<Employee> sup2 = Employee :: new;
System.out.println(sup2.get());
}
@Test
public void test2(){
// Lambda表达式
Function<Integer,Employee> func1 = id -> new Employee(id);
Employee employee = func1.apply(1001);
System.out.println(employee);
System.out.println("*******************");
// 构造器引用
Function<Integer,Employee> func2 = Employee :: new;
Employee employee1 = func2.apply(1002);
System.out.println(employee1);
}
@Test
public void test3(){
// Lambda表达式
BiFunction<Integer,String,Employee> func1 = (id,name) -> new Employee(id,name);
System.out.println(func1.apply(1001,"Tom"));
System.out.println("*******************");
// 构造器引用
BiFunction<Integer,String,Employee> func2 = Employee :: new;
System.out.println(func2.apply(1002,"Tom"));
}
数组构造引用
数组类型名[]::new
: 要求Lambda体只有一条语句并且是创建一个数组对象,接口中抽象方法的形参接收的是数组对象的长度
@Test
public void test4(){
// Lambda表达式
Function<Integer,String[]> func1 = length -> new String[length];
String[] arr1 = func1.apply(5);
System.out.println(Arrays.toString(arr1));
System.out.println("*******************");
// 数组引用
Function<Integer,String[]> func2 = String[] :: new;
String[] arr2 = func2.apply(10);
System.out.println(Arrays.toString(arr2));
}