当我们使用lambda表达式去创建一个匿名方法时,有时我们并没有做什么事情,仅仅是使用了对象中一个存在的方法。这种情况下,通过对象的方法名就能够很明显的推断出要使用 的方法,java8中的方法引用能够做到这一点。
首先创建一个Person对象。
public classPerson {public enumSex {
MALE, FEMALE
}
String name;
LocalDate birthday;
Sex gender;
String emailAddress;public intgetAge() {//...
}publicCalendar getBirthday() {returnbirthday;
}public static intcompareByAge(Person a, Person b) {returna.birthday.compareTo(b.birthday);
}}
然后有一组person对象,想通过生日进行排序,那么传统的方法是,实现Comparator接口
Person[] rosterAsArray = roster.toArray(newPerson[roster.size()]);class PersonAgeComparator implements Comparator{public intcompare(Person a, Person b) {returna.getBirthday().compareTo(b.getBirthday());
}
}
Arrays.sort(rosterAsArray,newPersonAgeComparator());
调用的sort方法如下,传入数组和 实现了Comparator的对象
static void sort(T[] a, Comparator super T> c)
因为Comparator接口是一个函数式接口,所以可以用lambda表达式代替实现了Comparator接口的类对象。
Arrays.sort(rosterAsArray,
(Person a, Person b)->{returna.getBirthday().compareTo(b.getBirthday());
}
);
然而匿名方法是根据生日对Person进行排序,这种方法功能已经在Person类中存在,所以我们可以直接使用lambda表达式调用
Arrays.sort(rosterAsArray,
(a, b)->Person.compareByAge(a, b)
);
因为lambda表达式调用存在的方法,可以使用方法应用代替lambda表达式
Arrays.sort(rosterAsArray, Person::compareByAge);
参数列表从与引用方法参数一致,JRE能够推断出方法参数类型,是(Person, Person)
方法体是Person.compareByAge,这样提高了方法的重用性
引用的方法包括:静态方法,实例方法,特定类型的任意对象方法引用,构造方法引用
KindExample
Reference to a static method
ContainingClass::staticMethodName
Reference to an instance method of a particular object
containingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type
ContainingType::methodName
Reference to a constructor
ClassName::new
引用静态方法,如上面例子所示
Person::compareByAge
引用实例方法,创建实例,就可以应用对象中的任意方法
classComparisonProvider {public intcompareByName(Person a, Person b) {returna.getName().compareTo(b.getName());
}public intcompareByAge(Person a, Person b) {returna.getBirthday().compareTo(b.getBirthday());
}
}
ComparisonProvider myComparisonProvider= newComparisonProvider();
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
特定类型的任意对象方法引用,例如String,和上面引用几乎相同,只是应用于基本数据类型等
String[] stringArray = { "Barbara", "James", "Mary", "John","Patricia", "Robert", "Michael", "Linda"};
Arrays.sort(stringArray, String::compareToIgnoreCase);
引用构造方法
public static , DEST extends Collection>DEST transferElements(
SOURCE sourceCollection,
SuppliercollectionFactory) {
DEST result=collectionFactory.get();for(T t : sourceCollection) {
result.add(t);
}returnresult;
}
函数式接口Supplier能够调用无参构造函数,返回一个对象,
Set rosterSetLambda =transferElements(roster, ()-> { return new HashSet<>(); });
也可以使用构造方法引用代替lambda表达式,构造对象
Set rosterSet = transferElements(roster, HashSet::new);
JAVA编译器能够推断出你想创建一个容器,所以可以指定容器包含的类型,如下
Set rosterSet = transferElements(roster, HashSet::new);