方法引用
方法引用是java8引入lambda表达式之后的一个特性,在日常的开发工作中经常使用,可以看做是一种函数指针(function pointer),也可以简单看做lambda表达式的一种语法糖。
方法引用的分类
可以将方法引用分为四种:
- 类::static方法
- 对象::实例方法
- 类::实例方法
- 构造函数引用
前两种应该很好理解,现在来简单记录下第三种。
类::实例方法的方法引用
这个看起来并不符合常规,类应该去调用static方法才对,为什么可以直接调用实例方法呢?以代码方式演示会比较好理解。
准备一个java bean。
1 | public class Student { |
可以看到这个Student类中有根据name和score进行比较的方法。
测试类::static方法这种方法引用方式:
1 | private static void 类实例方法() { |
可以看到这里students.sort(Student::compareByName);
是可以直接传入compareByName方法的。List.sort方法的参数是个Comparator接口,而compareByName返回的是int类型,这里编译器也没有报错。
其实这行就是相当于另外一种写法的
students.sort((st1, st2) -> st1.compareByName(st2));
这里鼠标点击箭头,可以直接跳转到Comparator接口的,这里的类::实例方法,其实并不是指的是这个实例方法,而是对这个students数组中的每个元素去应用这个compareByName方法,而进行比较的是从数组的第一个元素调用compareByName方法,这里的参数就是第二个元素。
这里也可以打个断点去看到compareByName是被调用两次的。(list中有三个元素)
default方法彩蛋
默认方法也是java8新增的一个特性,用来解决接口向下(或者老版本)兼容的问题。
这里看到一个有趣的点:当两个接口中有同名默认方法,子类同时实现这两个接口,会出现什么情况呢?
1 | public interface MyInterface1 { |
1 | public interface MyInterface2 { |
1 | public class 同名默认方法测试 implements MyInterface1, MyInterface2 { |
这里当没有指定实现的到底是哪个接口中的默认方法会编译不通过。(这类是用的一种特殊的写法:MyInterface1.super.myMethod()
去指定对应的默认方法)。