上一篇我们我们讲解了《Spring Boot实战1-函数式编程-Lambda表达式》,这节我们讲解函数式编程的另外一个重要概念:方法引用。
![a9715c85111d544ec4edc39222503011.png](https://img-blog.csdnimg.cn/img_convert/a9715c85111d544ec4edc39222503011.png)
4 Method Reference-方法引用
方法引用让我们可以使用已有的方法定义,并像Lambda表达式一样可以作为方法的参数。Java中方法引用使用“::”两个冒号表示。
4.1 构造器方法引用
构造方法的引用使用“类名::new”来定义。
- 无参数构造:构造器不接受参数,返回新建的Person对象,符合Supplier函数接口的定义,使用基于Lambda表达式的Supplier函数接口实现与方法引用是等同的。
Supplier emptyConstructor = Person::new;Supplier emptyConstructorLambda = () -> new Person();Person person1 = emptyConstructor.get();Person person1Lambda = emptyConstructorLambda.get();
- 一个参数构造:构造器接受一个参数,返回新建的Person对象,符合Function函数接口的定义,同样使用基于Lambda表达式的Function函数接口实现与方法引用是等同的。
Function nameConstructor = Person::new;Function nameConstructorLambda = name -> new Person(name);Person person2 = nameConstructor.apply("wyf");Person person2Lambda = nameConstructorLambda.apply("wyf");
- 两个参数构造:构造器接受两个参数,返回新建的Person对象,符合BiFunction函数接口的定义,同样使用基于Lambda表达式的BiFunction函数接口实现与方法引用是等同的。
BiFunction nameAndGenderConstructor = Person::new;BiFunction nameAndGenderConstructorLambda = (name, gender) -> new Person(name, gender);Person person3 = nameAndGenderConstructor.apply("www", Gender.FEMALE);Person person3Lambda = nameAndGenderConstructorLambda.apply("www", Gender.FEMALE);
- 三个参数构造:构造器接受三个参数,返回新建的Person对象,符合我们自定义的TriFunction函数接口的定义,同样使用基于Lambda表达式的TriFunction函数接口实现与方法引用是等同的。
TriFunction allConstructor = Person::new;TriFunction allConstructorLambda = (name, gender, weight) -> new Person(name, gender, weight);Person person4 = allConstructor.apply("www", Gender.FEMALE, 110);Person person4Lambda = allConstructorLambda.apply("www", Gender.FEMALE, 110);
4.2 静态方法引用
静态方法引用可以让我们使用方法引用的方式调用类的静态方法,格式为“类名::静态方法”,如:
IntFunction intToStringFunction = Integer::toString;//1IntFunction intToStringFunLambda = i -> Integer.toString(i);//2System.out.println(intToStringFunction.apply(123));System.out.println(intToStringFunLambda.apply(123));
- Integer::toString,toString方法是Integer类的静态方法,toString方法的参数和返回值符合IntFunction函数接口的定义;
- Lambda表达式等同于第1句。
4.3 实例方法引用
类的实例的方法的引用让我们使用方法引用的方式调用实例对象的方法,格式为“实例对象名::实例方法”,如:
Person person = new Person("www", Gender.FEMALE, 80);Consumer walkConsumer = person::walk;walkConsumer.accept("黄山路");
walk方法是Person类实例的方法:
public void walk(String roadName){ System.out.println(name + "在" + roadName +"上行走");}
4.4 引用特定类的任意对象的方法
还有另外一种形式实例方法的引用,格式为"类型名::实例方法",如:
List people = Arrays.asList(new Person("wyf", Gender.MALE, 100), new Person("www", Gender.FEMALE, 80), new Person("foo", Gender.FEMALE, 90));people.forEach(Person::sayName);people.forEach(person -> person.sayName());
此处的sayName方法是实例对象方法,people列表里的三个任意的Person实例均可以调用这个方法;注意和上面“实例方法引用”的区别,“实例方法引用”只针对一个实例对象进行方法引用,而我们当前的“引用特定类的任意对象的方法”可以对people列表里任意Person实例对象进行方法引用。
sayName方法是Person类的方法:
public void sayName(){ System.out.println("我的名字是:" + name);}
从上面4种方法引用与Lambda表达式的对比我们可以知道,在调用现有类的已有方法的时候的时候,方法引用比Lambda表达式更自然,可读性更强。比如上面的例子:
people.sort((p1, p2) -> p1.getWeight().compareTo(p2.getWeight()));
也可以用方法引用改写成:
people.sort(Comparator.comparing(Person::getWeight));