java8新特性专题之四、lambda方法引用和构造器引用
方法引用例子1
- landscape
Java8的lambda引入了三种方法引用,构造器引用,及数组引用,以减少代码的开发。需要注意的是,如果需要使用此特性,必须方法返回值类型、参数数量与类型与函数式接口保持一致。
- 实例
- 对象 - 实例方法使用场景
当对象的实例方法已经实现了函数式接口将要实现的功能,且实例方法的参数数量、参数类型、返回类型与函数式接口一致时,可以使用此特性。使用方式为:
对象::方法名
/** * @author: zhuocc2 * @date: 2019-09-02 4:53:18 PM * @Package: lambda * @Description: 对象 - 实例方法 使用场景。 * 当已经实例的方法已经实现了lambda将要实现的功能,可以使用此方式。 * 但需要lambda函数式接口的参数与返回值与实例方法的参数与返回值相同 * 使用方式 对象::方法名 */ @Test public void objectInstance() { PrintStream sysOut = System.out; Consumer<String> consumer = sysOut::println; consumer.accept("对象-实例方法运用"); }
输出
对象-实例方法运用
- 类 - 静态方法使用场景
当类的静态方法已经实现了函数式接口将要实现的功能,且实例方法的参数数量 、参数类型、返回类型与函数式接口一致时,可以使用此特性。使用方式为:
类::方法名
/** * @author: zhuocc2 * @date: 2019-09-02 5:27:39 PM * @Package: lambda * @Description: TODO 类 - 静态方法 使用场景 * 当类里已经实现了lambda将要实现的功能,可以使用此方式。只需参数与返回与lambda函数式接口保持一致即可。 * 使用方式 类名::方法名 */ @Test public void classStaticMethod() { Comparator<Integer> comparator = Integer::compare; System.out.println(comparator.compare(2, 1)); }
输出
1
- 类 - 实例方法使用场景
当实例方法的第一个参数为实例方法的调用者,第二个参数为实例方法的参数时,且实例方法的参数数量与类型、返回值类型与函数式接口一致时,可以使用此特性。使用方式为:
类::方法名
@Test public void classInstance() { BiPredicate<String, String> bp = String::equals; boolean test = bp.test("2", "2"); System.out.println(test); }
输出true
- 构造器引用使用场景
当构造器的参数列表与函数式接口的参数列表一致时,可以使用此特性。使用方式为:
public class TestConstruct { private String str = null; public TestConstruct(String str) { this.str = str; System.out.println(str); } public TestConstruct(String str1, String str2) { System.out.println(str1 + str2); } public String getStr() { return this.str; } }
/** * @author: zhuocc2 * @date: 2019-09-03 9:24:04 PM * @Package: lambda * @Description: TODO 构造器引用 */ @Test public void constructReference() { Function<String, TestConstruct> fun = TestConstruct::new; TestConstruct construct = fun.apply("str"); System.out.println(construct.getStr()); }
str
str
- 数组引用
/** * @author: zhuocc2 * @date: 2019-09-03 9:30:22 PM * @Package: lambda * @Description: TODO 数组引用 */ @Test public void arrayReference() { Function<Integer, Float[]> fun = Float[]::new; Float[] array = fun.apply(20); System.out.println(array.length); }
输出20
方法引用例子2
一、 方法引用: 若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”
要求 方法的参数和返回值类型 和 函数式接口中的参数类型和返回值类型保持一致。
主要有三种语法格式:
对象 :: 实例方法名
Consumer<String> consumer1 = System.out::print; //通过 方法引用 实现Lambda体。 consumer1.accept("Hello World!");
类 :: 静态方法名
Comparator<Integer> comparator1 = Integer::compare; 等价于
Comparator<Integer> comparator2 = (x, y) -> Integer.compare(x,y);
类 :: 实例方法名
//Lambda表达式参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用 类名 :: 方法名 BiPredicate<String, String> biPredicate = (x,y) -> x.equals(y); BiPredicate<String,String> biPredicate1 = String :: equals;
二、构造器引用: 构造器中的参数类型和函数式接口中的参数类型一致。
Supplier<Date> supplier = Date :: new; Date date = supplier.get(); long time = date.getTime();
三、数组引用
Function<Integer, String[]> function = String[]::new; String[] apply = function.apply(10); System.out.println(apply.length); // 10
方法引用例子3
当要传递给Lambda体的操作,已经有实现的方法,就可以使用方法引用!
实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致
方法引用使用操作符“::”将方法名和对象或者类的名字分隔开来。
三种使用情况:
- 对象::实例方法
- 类::静态方法
- 类::实例方法
例如:
(x)->System.out.println(x);
等同于:
System.out::println;
例如:
BinaryOperator<Double> bo=(x,y)->Math.pow(x,y)
等同于:
BinaryOperator<Double> bo=Math::pow;
例如:
compare((x,y)->x.equals(y),“abcdef”,“abcdef”);
等同于
compare(String::equals,“abcdef”,“abcdef”);
注意:当需要引用方法的第一个参数是调用对象,并且第二个参数是需要引用方法的第二个参数(或无参数)时:ClassName::mothodName
构造器引用
格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。
可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一直
例如:
Function<Integer,MyClass> fun=(n)->new MyClass(n);
等同于:
Function<Integer,MyClass> fun=MyClass::new;
数组引用
格式:type[]::new
例如:
Function<Integer,Integer[]> fun=(n)->new Integer[n];
等同于:
Function<Integer,Integer[]> fun=Integer[]::new;
@Test public void test6() { /*************** 方法的引用 ****************/ // 类::静态方法名 Comparator<Integer> bb = Integer::compare; System.out.println(bb.compare(3, 2)); Comparator<Integer> cc = (x, y) -> Integer.compare(x, y); System.out.println(cc.compare(3, 2)); Comparator<Integer> dd = (x, y) -> x.compareTo(y); System.out.println(dd.compare(3, 2)); Comparator<Integer> ee = Integer::compareTo; System.out.println(ee.compare(3, 2)); // 类::实例方法名 BiPredicate<String, String> bp = (x, y) -> x.equals(y); System.out.println(bp.test("a", "b")); BiPredicate<String, String> bp1 = String::equals; System.out.println(bp1.test("a", "b")); // 对象::实例方法名 Consumer<String> con1 = x -> System.out.println(x); con1.accept("abc"); Consumer<String> con = System.out::println; con.accept("abc"); Emp emp = new Emp("上海", "xiaoMIng", 18); Supplier<String> supper1 = () -> emp.getAddress(); System.out.println(supper1.get()); Supplier<String> supper = emp::getAddress; System.out.println(supper.get()); /*************** 构造器的引用 ****************/ // 无参构造函数,创建实例 Supplier<Emp> supper2 = () -> new Emp(); Supplier<Emp> supper3 = Emp::new; Emp emp1 = supper3.get(); emp1.setAddress("上海"); // 一个参数 Function<String, Emp> fun = address -> new Emp(address); Function<String, Emp> fun1 = Emp::new; System.out.println(fun1.apply("beijing")); // 两个参数 BiFunction<String, Integer, Emp> bFun = (name, age) -> new Emp(name, age); BiFunction<String, Integer, Emp> bFun1 = Emp::new; System.out.println(bFun1.apply("xiaohong", 18)); } static class Emp { private String address; private String name; private Integer age; public Emp() { } public Emp(String address) { this.address = address; } public Emp(String name, Integer age) { this.name = name; this.age = age; } public Emp(String address, String name, Integer age) { super(); this.address = address; this.name = name; this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Emp [address=" + address + ", name=" + name + ", age=" + age + "]"; } }
作者:十七家的猫
链接:https://www.jianshu.com/p/f2ab2db6fe2b
来源:简书