- 方法引用实际上是lambda表达式的一种特殊形式,也就是说是对已经存在的lambda表达是的简化。方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。
- 方法引用的标示一般是双冒号“::"。所以方法引用的标准形式为:类名::方法名 (方法名不需要加括号)。一般有以下四种形式:
类型 | 示例 | 说明 |
---|---|---|
引用静态方法 | Class::staticMethodName | 类名::静态方法名 |
引用某个对象的实例方法 | Object::instanceMethodName | 对象::实例方法名 |
引用某个类型的任意对象的实例方法 | Type::methodName | 类名::实例方法名 |
引用构造方法 | ClassName::new | 类名::new |
- 方法引用实例代码
1.引用静态方法
public class Student {
private String name;
private int score;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public Student() {
}
public static int compareScore(Student s1,Student s2){
return s1.getScore()-s2.getScore();
}
}
该对象设置了简单的name,score属性,并且最下方有一个静态的比较方法。接下来按照传入的信息,把学生对象由小到大排序。
使用标准的Lambda表达式代码如下:
public class MainTest {
public static void main(String[] args) {
Student s1 = new Student("张三",80);
Student s2 = new Student("李四",90);
Student s3 = new Student("王五",70);
Student s4 = new Student("赵六",65);
Student s5 = new Student("钱多多",98);
List<Student> students = Arrays.asList(s1,s2,s3,s4,s5);
students.sort((o1,o2)->o1.getScore()-o2.getScore());
students.forEach(student -> System.out.println(student.getName()+"||"+student.getScore()));
}
}
而我们在对象中定义了一个静态的比较方法的和Lambda标准表达式中比较的逻辑相同,因此我们可以使用类名::静态方法来替代;具体代码如下
//类名::静态方法
students.sort(Student::compareScore);
students.forEach(student -> System.out.println(student.getName()+"||"+student.getScore()));
2. 引用某个对象的实例方法
这里我名就需要引入一个新的比较类,该类中只有一个简单的比较方法
public class StudentComparator {
public int compareScore(Student s1,Student s2){
return s1.getScore()-s2.getScore();
}
}
如果我们通过调用这个方法进行比较,标准的Lambda表达式如下:
StudentComparator studentComparator = new StudentComparator();
//Lambda表达式
students.sort((o1,o2)->studentComparator.compareScore(o1,o2));
students.forEach(student -> System.out.println(student.getName()+"||"+student.getScore()));
简化为方法引用就是对象名::实例方法名(只有这个是对象名,个人觉得可能是要new一个对象才能引用其中的方法):
StudentComparator studentComparator = new StudentComparator();
//方法引用
students.sort(studentComparator::compareScore);
students.forEach(student -> System.out.println(student.getName()+"||"+student.getScore()));
- 引用某个类型的任意对象的实例方法
这种情况相对来说比较难理解,因为他是以自身作为一个参数传入,第二个参数作为比较的,这就需要我们队Student对象添加一个比较方法:
public int compareByScoreNew(Student student){
return this.getScore() - student.getScore();
}
如果使用标准的Lambda表达式:
students.sort((o1,o2)->o1.compareByScoreNew(o2));
students.forEach(student -> System.out.println(student.getName()+"||"+student.getScore()));
修改为方法引用看起来就比较奇怪:
students.sort(Student::compareByScoreNew);
students.forEach(student -> System.out.println(student.getName()+"||"+student.getScore()));
4. 引用构造方法
定义一个Supplier接口如下:
@FunctionalInterface
public interface Supplier<T> {
T get();
}
调用的方法如下:
Supplier<Student> studentSupplier = Student::new;
Student student = studentSupplier.get();
student.setName("1");
student.setScore(55);
System.out.println("student:"+student.getScore());
注:通过这种方法创建对象,有一个必须的前提,那就是对象中一定要有无参数的构造方法。