【从零单排】浅析Java 8新特性Method Reference
什么是方法引用
我们知道了什么是Lambda Expression以及如何使用,那么,Method References又是什么呢?Oracle Java Docs中这样说:
They are compact, easy-to-read lambda expressions for methods that already have a name.
也就是说,它是把已经定义好的有名字的方法,当作Lambda Expression来使用。
它的常用语法为:className::methodName
。
理解方法引用
通过一个例子来看:有一个数组,里面放了一堆Person对象,现在想要对它根据生日进行排序。
Person类
public class Person {
LocalDate birthday;
public Calendar getBirthday() {
return birthday;
}
public static int compareByAge(Person a, Person b) {
return a.birthday.compareTo(b.birthday);
}
}
常规写法
Person[] rosterAsArray = roster.toArray(new Person[roster.size()]);
class PersonAgeComparator implements Comparator<Person> {
public int compare(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
}
Arrays.sort(rosterAsArray, new PersonAgeComparator());
Lambda Expression写法1:手动比较两个Date
Arrays.sort(rosterAsArray,
(Person a, Person b) -> {
return a.getBirthday().compareTo(b.getBirthday());
}
);
分析这个Lambda Expression
- 首先,它overwrite了Comparator.compare()方法。
- 然后,看一下compare()的参数:int compare(T o1, T o2),它的输入是两个类型一致的对象,返回值为int型。对应到表达式:
- 左边:(Person a, Person b),定义了输入参数,两个Person类型的对象。
- 右边:a.getBirthday().compareTo(b.getBirthday()),定义了输出参数,类型为int。
我们发现,对于右边,不一定要调用Date.compareTo()方法,其他任意自定义的方法都可以,只需要满足输入输出参数一致即可。
正好,Person类里面已经定义了一个compareByAge()方法可以直接拿过来替换。于是,可以改成这样:
Lambda Expression写法2:调用已经定义好的方法
Arrays.sort(rosterAsArray,
(Person a, Person b) -> {
return Person.compareByAge(a, b);
}
);
再对其分析,可以发现,左边(Person a, Person b)其实是冗余信息,因为右边Person.compareByAge(a, b)方法已经定义好了输入输出。
所以,上面的代码可以简化如下:
Method Reference写法
Arrays.sort(rosterAsArray, Person::compareByAge);
几种类型
Method Reference有以下几种类型:
- 引用静态方法:
ClassName::staticMethodName
- 引用构造方法:
ClassName::new
- 引用某个实例上的实例方法应用:
instanceReference::instanceMethodName
- 引用某个类型上的实例方法引用:
ClassName::instanceMethodName
在使用“某个类型上的实例方法引用”时,需要传入实例化参数;而在使用“某个实例上的实例方法应用”时,因为已经实例化过了所以并不需要。