方法引用可以看做式lambda表达式的语法糖, 用于替换lambda表达式,使代码更加精简,我们可以将方法引用看做是一个函数指针, 指向被引用的方法其能够替代lambda表达式的原因在于某些lambda表达式的参数,返回值,功能实现与被引用的方法皆一致.方法引用共分4类:
1. 类名::静态方法名
@Data
@AllArgsConstructor
public class Student {
private String name;
private Integer score;
public static int compareStudentByScore(Student s1, Student s2) {
return s1.getScore() - s2.getScore();
}
public static int compareStudentByName(Student s1, Student s2) {
return s1.getName().compareToIgnoreCase(s2.getName());
}
}
@Test
public void Test() {
Student s1 = new Student("a", 10);
Student s2 = new Student("b", 90);
Student s3 = new Student("c", 50);
Student s4 = new Student("d", 40);
List<Student> students = Arrays.asList(s1, s2, s3, s4);
// 传统lambda方式排序
students.sort((x, y) -> Student.compareStudentByScore(x, y));
students.forEach(System.out::println);
System.out.println("---------------");
// 利用方法引用排序, 不用传参数在于编译器的自动推断
students.sort(Student::compareStudentByScore);
students.forEach(System.out::println);
}
注意:这两个完全不一样,不要搞混了:
classname::staticmethod 方法引用,是个指针
classname.staticmethod 方法的调用
2. 引用名(对象名)::实例方法名, 这和静态方法引用类似, 区别不大
public class StudentComparator {
public int compareStudentByScore(Student s1, Student s2) {
return s1.getScore() - s2.getScore();
}
public int compareStudentByName(Student s1, Student s2) {
return s1.getName().compareToIgnoreCase(s2.getName());
}
}
@Test
public void Test2() {
Student s1 = new Student("a", 10);
Student s2 = new Student("b", 90);
Student s3 = new Student("c", 50);
Student s4 = new Student("d", 40);
List<Student> students = Arrays.asList(s1, s2, s3, s4);
// 传统lambda写法
StudentComparator comparator = new StudentComparator();
students.sort((x, y) -> comparator.compareStudentByScore(x, y));
students.forEach(System.out::println);
System.out.println("--------------");
// 对象方法引用写法, 和静态的比较像, 对象和类的区别
students.sort(comparator::compareStudentByScore);
students.forEach(System.out::println);
System.out.println("--------------");
}
3. 类名::实例方法名
@Data
@AllArgsConstructor
public class Student {
private String name;
private Integer score;
public int compareByScore(Student student) {
return this.getScore() - student.getScore();
}
public int compareByName(Student student) {
return this.getName().compareToIgnoreCase(student.getName());
}
}
/**
类::实例方法 形式的方法引用
这个方法依然是对象调用的, 用的是lambda表达式的第一个参数
*/
@Test
public void Test3() {
Student s1 = new Student("a", 10);
Student s2 = new Student("b", 90);
Student s3 = new Student("c", 50);
Student s4 = new Student("d", 40);
List<Student> students = Arrays.asList(s1, s2, s3, s4);
students.sort(Student::compareByScore);
students.forEach(System.out::println);
System.out.println("-----------------------");
// 加深理解
List<String> cities = Arrays.asList("qingdao", "chongqing", "tianjin", "beijing");
Collections.sort(cities, (c1, c2) -> c1.compareToIgnoreCase(c2));
Collections.sort(cities, String::compareToIgnoreCase);
}
4. 构造方法引用: 类名::new
public String getString(Supplier<String> supplier) {
return supplier.get() + "test";
}
public String getString2(String str, Function<String, String> function) {
return function.apply(str);
}
/**
* 注意, 这里String::new两次调用的构造方法是不同的, 因为接口的需要不同
* 这个例子是说明 类名::new 这个方法引用会自动选择符合参数约定的方法来调用
*/
@Test
public void Test4() {
MethodReferenceTest methodReferenceTest = new MethodReferenceTest();
System.out.println(methodReferenceTest.getString(String::new));
System.out.println(methodReferenceTest.getString2("hello",String::new));
}