鏈接:https://www.zhihu.com/question/45218076/answer/98632631
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
方法引用是當你想把一個方法當作一個“函數指針”傳給別的方法用時有用的。
例如說,我有個ArrayList想把里面每個元素都打印出來,每個元素一行。那么Java 8之前會這樣寫:
for (ElementType e : list) { System.out.println(e); }
list.forEach(e -> System.out.println(e));
list.forEach(System.out::println);
僅此而已。
重點:- System.out是一個PrintStream實例的引用;System.out::println 是對一個實例方法的引用
- 該引用同時指定了對實例(System.out)的引用以及對方法(PrintStream::println)的引用
- System.out::println 不是 System.out.println 的等價物;前者是一個方法引用表達式,而后者不能單獨作為一個表達式,而必須在后面跟上由圓括號包圍的參數列表來構成方法調用表達式。
- System.out::println 可以看作 lambda表達式 e -> System.out.println(e) 的縮寫形式。
鏈接:https://www.zhihu.com/question/45218076/answer/125250908
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
無意間看到了,還是答一下吧,這個時間點上我想題主如果繼續學習的話應該早已經明白了問題的答案,所以這篇答案就算留給后面無意間看到而又對此困惑的朋友吧:
實際上這個方法引用僅僅是一個Lambda表達式簡化寫法的語法糖,System.out::print和System.out.print()的語義完全不同,就像R大所說,用::而不用.就是為了區分語義,即使用了“::”都造成了困惑,那么用“.”的話恐怕困惑會更嚴重吧。
如果后來的朋友看不明白這個解釋的話,那么首先就要明白Java8增加的這個Lambda表達式是干什么的,其實Lambda表達式主要解決的問題就是“如何把一個動作傳入一個方法?”在C/C++中,我們可以給函數傳入一個函數指針來做到這一點,C#中我們可以將一個委托傳入方法中;本質上即是將一個方法/函數當成參數傳給另一個方法/函數,那么之前Java是沒有類似的語法的,一直以來Java中是如何解決這個問題的呢?
事實上Java一直以來的解決方案都是在方法參數上接收一個接口,接口中有需要的動作(即方法),調用的時候只要傳入一個實現這個接口的對象即可間接地把方法傳進去,例如創建線程的代碼:new Thread(new Runnable() { @Override public void run() { //動作 } }).start();
(方法參數列表) -> {方法體}
所以上面Thread的例子就能寫成:
new Thread(() -> { //動作 }).start();
List<String> list = Arrays.asList("真","可","愛"); list.forEach((String item) -> System.out.print(item)); //這里的參數列表具有一定的類型推倒功能,所以也可以進一步省略寫為: list.forEach(item -> System.out.print(item));
List<String> list = Arrays.asList("真","可","愛"); list.forEach(System.out::print);
既然只是想把每次遍歷得到的String item傳入print方法,那么簡略的用一個“方法引用”來引用這個方法就行了,這里這個System.out::print僅僅是等效於item -> System.out.print(item),和System.out.print()的語義是不同的,這里僅僅表達的是將唯一的參數傳入System.out這個流對象的print方法的Lambda表達式而已,所以這里也不加括號;System.out.print()的語義就是直接調用方法了。這個語法糖除了用於普通方法外,如果是構造函數的方法引用,那么就是“ClassName::new”這種寫法。這就是上面這個現象我自己的理解。
如果您對此還想繼續深入學習的話,建議您學習Java 8增加的Stream<T> API,它是Java對於函數式編程的一個實踐,學習它有助於理解函數式編程的一些基本思想,並對Scala、Spark編程的學習有一定好處。