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方法。

posted @ 2018-03-29 16:23  千百  阅读(224)  评论(0编辑  收藏  举报