Java 8之方法引用
文章目录[隐藏]
Java 8开始支持Lambda表达式,其避免了我们创建匿名内部类的麻烦,形式上更加优雅简洁易读。而如果我们Lambda表达式中只是调用一个已经封装过的方法,则显得过于繁琐、不够简约,为此Java 8在支持Lambda表达式的同时,也提供了一个语法糖:方法引用
方法引用
方法引用有如下4种使用形式:
- 类名::静态方法名
- 对象实例名::实例方法名
- 类名::实例方法名
- 类名::new
类名::静态方法名
对于静态方法,通过类名::静态方法名的方式,即可调用该方法
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(-12);
set.add(3);
set.add(-8);
set.add(4);
// 方式1: Lambda 表达式
System.out.println("------------ Lambda Expression ------------");
set.forEach((e) -> {
test.getNum(e);
});
// 方式2: 方法引用
System.out.println("\r\n------------ Method Reference ------------");
set.forEach(test::getNum);
}
public static void getNum(Integer a) {
Integer num = Math.abs(a);
System.out.println("num: " + num);
}
测试结果如下,表明上述两种形式作用是一致的,函数式接口中的参数全部传入所指定的静态方法中
------------ Lambda Expression ------------ num: 3 num: 4 num: 8 num: 12 ------------ Method Reference ------------ num: 3 num: 4 num: 8 num: 12
对象实例名::实例方法名
对于实例方法,可以通过 对象实例名::实例方法名 的方式来使用,代码如下所示:
public static void main(String[] args) {
Set<Student> set = new HashSet<>();
for(int i=0; i<2; i++) {
Student student = new Student();
student.setAge(i);
student.setId(i);
student.setName(String.valueOf(i));
set.add(student);
}
Student stu = new Student();
stu.setName("Aaron");
stu.setId(78);
stu.setAge(24);
// 方式1: Lambda 表达式
System.out.println("------------ Lambda Expression ------------");
set.forEach( (e) -> {
stu.getDetail(e);
} );
// 方式2: 方法引用
System.out.println("\r\n------------ Method Reference ------------");
set.forEach(stu::getDetail);
}
@Data
class Student{
private Integer age;
private Integer id;
private String name;
public void getDetail() {
System.out.println("call: " + this);
}
public void getDetail(Student s) {
System.out.println("call: " + this);
System.out.println("param: " + s);
}
}
测试结果如下,表明上述两种形式作用是一致的。函数式接口中的参数全部传入所指定的实例方法中,而实例方法的调用者即为在lambda表达式和方法引用中指定的实例对象
Hello Word by Aaron ------------ Lambda Expression ------------ call: Student(age=24,id-78,name=Aaron) param: Student(age=0,id=0,name=0) call: Student(age=24,id-=78,name=Aaron) param: Student(age=1, id=1, name=1) ------------ Method Reference ------------ call: Student(age=24,id-78,name=Aaron) param: Student(age=0,id=0,name=0) call: Student(age=24,id-=78,name=Aaron) param: Student(age=1, id=1, name=1)
类名::实例方法名
对于实例方法,其实还可以通过 类名::实例方法名 的方式来使用,代码如下所示:
public static void main(String[] args) {
Set<Student> set = new HashSet<>();
for(int i=0; i<2; i++) {
Student student = new Student();
student.setAge(i);
student.setId(i);
student.setName(String.valueOf(i));
set.add(student);
}
Student stu = new Student();
stu.setName("Aaron");
stu.setId(78);
stu.setAge(24);
// 方式1: Lambda 表达式
System.out.println("------------ Lambda Expression ------------");
set.forEach( (e) -> {
e.getDetail();
} );
// 方式2: 方法引用
System.out.println("\r\n------------ Method Reference ------------");
set.forEach(Student::getDetail);
}
@Data
class Student{
private Integer age;
private Integer id;
private String name;
public void getDetail() {
System.out.println("call: " + this);
}
public void getDetail(Student s) {
System.out.println("call: " + this);
System.out.println("param: " + s);
}
}
测试结果如下,表明上述两种形式作用是一致的,此时在方法引用中函数式接口所传入的第一个参数即为实例方法的调用者,如果有剩余参数的话,其将全部传入所指定的实例方法中
Hello Word by Aaron ------------ Lambda Expression ------------ param: Student(age=0,id=0,name=0) param: Student(age=1, id=1, name=1) ------------ Method Reference ------------ param: Student(age=0,id=0,name=0) param: Student(age=1, id=1, name=1)
类名::new
对于构造器,可通过 类名::new 的方式来调用,代码如下所示:
public static void main(String[] args) {
String[] array = new String[]{"Aaron", "Bob", "Tony"};
List<String> list = Arrays.asList(array);
System.out.println("------------ Lambda Expression ------------");
List<Student> students1 = list.stream()
.map(str -> new Student(str) ) // 通过lambda
.collect(Collectors.toList());
students1.forEach(System.out::println);
System.out.println("------------ Method Reference ------------");
List<Student> students2 = list.stream()
.map(Student::new) // 方法引用
.collect(Collectors.toList());
students2.forEach(System.out::println);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Student{
private Integer age;
private Integer id;
private String name;
public Student(String name) {
this.name = name;
}
}
测试结果如下,表明上述两种形式作用是一致的:
------------ Lambda Expression ------------ student(age=null,id=null, name=Aaron) student(age=null,id=null, name=Bob) student(age=null,id=null, name=Tony) ------------ Method Reference ------------ student(age=null,id=null, name=Aaron) student(age=null,id=null,name=Bob) student(age=null,id=null, name=Tony)
本站文章主要用于个人学习记录,可能对您有所帮助,仅供参考!

