6.3.4 方法引用
有时,可能已经有现成的方法可以完成你想要传递到其他代码的某个动作。
例:假设你希望只要出现一个定时器事件就打印这个事件对象。当然,可以调用:
Timer t =new Timer(1000,event -> System.out.println(event));
但是,如果直接把println 方法传递到Timer构造器就更好了。具体的做法如下:
Timer t = new Timer(1000,System.out.println(event));
表达式System.out::println 是一个方法引用(method reference),它等价于lambda表达式x -> System.out.println(x)。
再来看一个例子,对字符串排序,而不考虑字母的大小写。可以传递已下方法表达式:
Arrays.sort(strings,String::compareToIgnoreCase)
从这些例子可以看出,要用::操作符分隔方法名与对象或类名。主要有三种情况:
object :: instanceMethod
Class :: staticMethod
Class :: instanceMethod
在前2种情况中,方法引用等价于提供方法参数的lambda表达式。前面已经提到,System.out::println 等价于x -> System.out.println(x). 类似的,Math::pow等价于(x,y) -> Math.pow(x,y)。
对于第三种情况,第一个参数会成为方法的目标。例如,String::compareToIgnoreCase 等同于(x,y) -> x.compareToIgnoreCase(y)。
类似于lambda表达式,方法引用不能独立存在,总是会转换为函数式接口的实例。可以在方法引用中使用this参数,例:
this::equals等同于 x -> this.equals(x)。使用super也是合法的。下面的方法表达式
super::instanceMethod
使用this作为目标,会调用给定方法的超类版本。
例:
1 class Greeter 2 { 3 public void greet() 4 { 5 System.out.println("Hello,world!"); 6 } 7 } 8 class TimedGreeter extends Greeter 9 { 10 public void greet() 11 { 12 Timer t =new Timer (1000,super::greet); 13 t.start(); 14 } 15 }
TimerGreeter.greet 方法开始执行时,会构造一个Timer,它会在每次定时器滴答时执行super::greet方法。这个方法会调用超类的greet方法。