- 1. 方法引用的概念
- 2. 方法引用的使用
- (1)实例 :: 非静态方法名
- (2)类名 :: 静态方法名
- (3)类 :: 非静态方法名 (有难度)
- 2. 构造器引用
- (1)无参构造器引用
- (2)单个参数构造器引用
- (3)两个参数的构造器引用
- 3. 数组引用
方法引用和构造器引用是基于Lambda 表达式的基础上产生的,关于Lambda表达式,可以看 这个帖子。 1. 方法引用的概念
当要传递给Lambda 体的操作,已经有现成的实现的方法了,就可以直接使用方法引用!
方法引用可以看做是Lambda 表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda 表达式的一个语法糖。
要求:实现函数式接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致(主要适用于下面的实例 :: 非静态方法名 和 类名 :: 静态方法名这两种情况,类名 :: 非静态方法名 这种情况比较特殊,后面会具体介绍)!
格式:使用操作符 :: 将类(或对象) 与 方法名分隔开来,可以通过如下三种形式使用方法引用:
- 实例 :: 非静态方法名
- 类名 :: 静态方法名
- 类名 :: 非静态方法名
// 例1
public class Main {
@Test
public void test() {
// Lambda 表达式的写法
Consumer consumer = str -> System.out.println(str);
consumer.accept("浙江欢迎你!!!");
PrintStream ps = System.out; // 实例
Consumer consumer2 = ps :: println;
consumer2.accept("浙江欢迎你!!!");
}
}
// 例2
public class Main {
@Test
public void test() {
Employee emp = new Employee(1001, "Tom", 23, 5600);
Supplier supplier = () -> emp.getName();
System.out.println(supplier.get());
Supplier supplier2 = emp :: getName;
System.out.println(supplier2.get());
}
}
(2)类名 :: 静态方法名
// 例1
public class Main {
@Test
public void test() {
Comparator comparator = (o1, o2) -> Integer.compare(o1, o2);
System.out.println(comparator.compare(11, 21));
Comparator comparator2 = Integer :: compare;
System.out.println(comparator2.compare(21, 11));
}
}
// 例2
public class Main {
@Test
public void test() {
// 函数型接口,因为第一次见到所以将实现匿名类的方式也写一下
Function function = new Function() {
@Override
public Long apply(Double value) {
return Math.round(value);
}
};
System.out.println(function.apply(110.11));
// 再用Lambda 表达式写一下
Function function2 = value -> Math.round(value);
System.out.println(function2.apply(211.985));
Function function3 = Math :: round;
System.out.println(function3.apply(985.211));
}
}
(3)类 :: 非静态方法名 (有难度)
// 例1
public class Main {
@Test
public void test() {
// Lambda 表达式写法
Comparator comparator = (o1, o2) -> o1.compareTo(o2);
System.out.println(comparator.compare("abc", "abd"));
Comparator comparator2 = String :: compareTo;
System.out.println(comparator2.compare("abc", "abd"));
}
}
// 例2
public class Main {
@Test
public void test() {
// Lambda 表达式写法,逻辑为判断两个字符串是否相同
BiPredicate biPredicate = (s1, s2) -> s1.equals(s2);
System.out.println(biPredicate.test("abc", "abc"));
BiPredicate biPredicate2 = String :: equals;
System.out.println(biPredicate2.test("abc", "abc"));
}
}
// 例3
public class Main {
@Test
public void test() {
// Lambda 表达式写法,输出员工姓名
Function function = (emp) -> emp.getName();
System.out.println(function.apply(new Employee(1001, "Tom", 23, 5600)));
Function function2 = Employee :: getName;
System.out.println(function2.apply(new Employee(1001, "Tom", 23, 5600)));
}
}
2. 构造器引用
构造器引用与方法引用类似,函数式接口的抽象方法形参列表和构造器的形参列表一致。
抽象方法的返回值类型为构造器所属类的类型。
(1)无参构造器引用借用 S u p p l i e r Supplier Supplier 接口中的 R R R g e t ( ) get() get() 方法实现。
public class Main {
@Test
public void test() {
// 借用Supplier接口 T get()
Supplier supplier = new Supplier() {
@Override
public Employee get() {
return new Employee();
}
};
Employee emp = supplier.get();
// 将匿名类改造成Lambda 表达式
Supplier supplier2 = () -> new Employee();
Employee emp2 = supplier2.get();
// 使用构造器引用
// 可以将 Employee的空参构造器看成函数 Employee new Employee()
Supplier supplier3 = Employee :: new;
Employee emp3 = supplier3.get();
}
}
(2)单个参数构造器引用
借用 F u n c t i o n Function Function 接口中的 R R R a p p l y ( T apply(T apply(T t ) t) t) 方法实现:
// 假设现在Employee类存在一个public Employee(int id)有参构造器
public class Main {
@Test
public void test() {
// 借用Function接口 R apply(T t)
Function function = new Function() {
@Override
public Employee apply(Integer id) {
return new Employee(id);
}
};
Employee emp = function.apply(1001);
// 将匿名类改造成Lambda 表达式
Function function2 = id -> new Employee(id);
Employee emp2 = function2.apply(1001);
// 类似地,使用构造器引用
Function function3 = Employee :: new;
Employee emp3 = function3.apply(1001);
}
}
(3)两个参数的构造器引用
借用 B i F u n c t i o n BiFunction BiFunction 接口 R R R a p p l y ( T apply(T apply(T t , U t, U t,U u ) u) u) 方法实现。
// 假设现在Employee类存在一个public Employee(int id, String name)有参构造器
public class Main {
@Test
public void test() {
// 借用BiFunction接口 R apply(T t, U u)
BiFunction biFunction = new BiFunction() {
@Override
public Employee apply(Integer id, String name) {
return new Employee(id, name);
}
};
Employee emp = biFunction.apply(1001, "Tom");
// 将匿名类改造成Lambda 表达式
BiFunction function2 = (id, name) -> new Employee(id, name);
Employee emp2 = biFunction2.apply(1001, "Tom");
// 类似地,使用构造器引用
BiFunction function3 = Employee :: new;
Employee emp3 = biFunction3.apply(1001, "Tom");
}
}
3. 数组引用
大家可以把数组看做为一个特殊的类,则写法与构造器引用一致。
数组引用使用 F u n c t i o n Function Function 接口中的 R R R a p p l y ( T apply(T apply(T t ) t) t) 方法实现。
public class Main {
@Test
public void test() {
// Integer传入的是创建数组的长度,采用匿名实现类的写法
Function function = new Function() {
@Override
public String[] apply(Integer length) {
return new String[length];
}
};
String[] strs = function.apply(10); // 创建了一个长度为5的String数组
System.out.println(Arrays.toString(strs));
// Integer传入的是创建数组的长度,采用Lambda表达式写法
Function function1 = length -> new String[length];
String[] strs1 = function1.apply(10); // 创建了一个长度为5的String数组
System.out.println(Arrays.toString(strs1));
// 类似地,使用构造器引用
Function function2 = String[] :: new;
String[] strs2 = function2.apply(10);
System.out.println(Arrays.toString(strs2));
}
}



