有些時候,你想要傳遞給其餘代碼的操做已經有實現的方法了。示例:java
button.setOnAction(event -> System.out.println(event));
若是你可以只將println方法傳遞給setOnAction方法,就更好了!下面是改後的代碼:ide
button.setOnAction(System.out::println);
表達式System.out::println是一個方法引用,等同於lambda表達式:函數
x -> System.out.println(x)
正如示例代碼所示:操做符將方法名和對象或類的名字分開來。如下三種主要的使用狀況:this
對象::實例方法spa
類::靜態方法code
類::實例方法對象
在前兩種狀況中,方法引用等同於提供方法參數的lambda表達式。如以前所述,System.out::println等同於 System.out.println(x)。類似的,Math::pow等同於(x,y) -> Math.pow(x,y)。在第三種狀況中,第一個參數會成爲執行方法的對象。例如String::compareToIgnoreCase等同於(x,y) -> x.compareToIgnoreCase(y)。接口
注意:若是有多個同名的重載方法,編譯器會試圖從上下文中找到最匹配的一個方法。例如,有兩個版本的Math.max方法,一個接收整型做爲參數,而另外一個接收double類型的值。究竟會選擇哪個方法,取決於Math::max被轉換爲的函數式接口的方法參數。同lambda表達式相似,方法引用也不會獨立存在,它們常常被用於轉換爲函數式接口的實例。編譯器
你還能夠捕獲方法引用中的this參數。例如,this::equals就等同於x -> this.equals(x)。你也能夠使用super對象,如:super::實例方法。示例:io
package java8; public class J2 { public static void main(String[] args) { Greeter g = new ConcurrentGreeter(); g.greet(); } } class Greeter { public void greet(){ System.out.println("Hello world!"); } } class ConcurrentGreeter extends Greeter{ @Override public void greet() { //super表明當前類的對象的父類對象,並非函數式接口的父實例對象 Thread t = new Thread(super::greet); t.start(); } }
package java8; public class J3 { public static void main(String[] args) { Greeter1 g = new Greeter1(); g.greet(); } } class Greeter1 { public void greet() { //this表明的當前類的對象,並非函數式接口的實例對象 Thread t = new Thread(this::printInfo); t.start(); } public void printInfo(){ System.out.println("test success!!"); } }