假设想要在按钮被点击时打印event对象,可以这样调用:
button.setOnAction(event -> System.out.println(event));
还能够只讲println方法传递给setOnAction方法,如下:
button.setOnAction(System.out::println);
表达式System.out::println是一个方法引用,等同于lambda表达式 x -> System.out.println(x)。
假设希望不区分大小写地对字符串进行排序,可以传入下面这个方法引用:
Arrays.sort(strings, String::compareToIgnoreCase);
::操作符将方法名和对象或类的名字分隔开来。一下是主要的三种使用情况:
对象 :: 实例方法
类 :: 静态方法
类 :: 实例方法
前两种情况中,方法引用等同于提供方法参数的lambda表达式。比如:Math::pow等同于(x, y) -> Math.pow(x, y)。
第三种情况中,第一个参数会成为执行方法的对象。比如:String::compareToIgnoreCase等同于(x, y) -> x.compareToIgnoreCase(y)。
如果有多个同名的重载方法,编译器会试图从上写文中找到最匹配的一个方法。例如有2个版本的Math.max方法,一个接收整型作为参数,而另一个接收double类型的值。选择哪个方法,取决于Math::max被转换为函数式接口的方法参数。同lambda表达式类似,方法引用也不会独立存在,它们经常被用于转换为函数式接口的实例。
可以捕获方法引用中的this参数。例如:this::equals 等同于 x -> this.equals(x)。也可以使用super对象,表达式为super::实例方法
该表达式会使用this作为执行方法的对象,并调用父类中指定的方法。以下代码说明该机制:
class Greeter {
public void greet(){
System.out.println("Hello world!");
}
}
class ConcurrentGreeter extends Greeter {
public void greet(){
Thread t = new Thread(super::greet);
t.start();
}
}
当线程启动时,会调用它的Runnable方法,然后执行super::greet并调用父类中的greet方法。