淺談對(duì)Java雙冒號(hào)::的理解
本文為個(gè)人理解,不保證完全正確。官方文檔中將雙冒號(hào)的用法分為4類,按照我的個(gè)人理解可以分成2類來(lái)使用。
官方文檔
官方文檔中將雙冒號(hào)的用法分為了以下4類:
用法 舉例 引用靜態(tài)方法 ContainingClass::staticMethodName 引用特定對(duì)象的實(shí)例方法 containingObject::instanceMethodName 引用特定類型的任意對(duì)象的實(shí)例方法 ContainingType::methodName 引用構(gòu)造函數(shù) ClassName::new
以下是我的理解
個(gè)人理解
雙冒號(hào)的作用
在使用雙冒號(hào)前我們要先搞清楚一個(gè)問(wèn)題:為什么要使用雙冒號(hào)?也就是雙冒號(hào)的作用是什么。雙冒號(hào)的設(shè)計(jì)初衷是為了化簡(jiǎn)Lambda表達(dá)式,不熟悉Lambda表達(dá)式的同學(xué)可以先了解一下。Lambda表達(dá)式的形式有兩種:
包含單獨(dú)表達(dá)式 :parameters -> an expression
list.forEach(item -> System.out.println(item));
包含代碼塊:parameters -> { expressions }
list.forEach(item -> { int numA = item.getNumA(); int numB = item.getNumB(); System.out.println(numA + numB);});
使用雙冒號(hào)可以省略第一種Lambda表達(dá)式中的參數(shù)部分,即item ->和調(diào)用方法的參數(shù)這兩部分。
例如:
//不使用雙冒號(hào)list.forEach(item -> System.out.println(item));//使用雙冒號(hào)list.forEach(System.out::println);
雙冒號(hào)的使用條件
使用雙冒號(hào)有兩個(gè)條件:
條件1條件1為必要條件,必須要滿足這個(gè)條件才能使用雙冒號(hào)。Lambda表達(dá)式內(nèi)部只有一條表達(dá)式(第一種Lambda表達(dá)式),并且這個(gè)表達(dá)式只是調(diào)用已經(jīng)存在的方法,不做其他的操作。
條件2由于雙冒號(hào)是為了省略item ->這一部分,所以條件2是需要滿足不需要寫參數(shù)item也知道如何使用item的情況。有兩種情況可以滿足這個(gè)要求,這就是我將雙冒號(hào)的使用分為2類的依據(jù)。
情況 舉例 Lambda表達(dá)式的參數(shù)與調(diào)用函數(shù)的參數(shù)完全一致 list.forEach(item -> System.out.println(item)) 調(diào)用的函數(shù)是參數(shù)item對(duì)象的方法且沒有參數(shù) list.stream().map(item -> item.getId())
一些栗子
Lambda表達(dá)式的參數(shù)與調(diào)用函數(shù)的參數(shù)完全一致時(shí)
靜態(tài)方法調(diào)用
//化簡(jiǎn)前l(fā)ist.forEach(item -> System.out.println(item));//化簡(jiǎn)后list.forEach(System.out::println);
非靜態(tài)方法調(diào)用
StringBuilder stringBuilder = new StringBuilder();//化簡(jiǎn)前IntStream.range(1, 101).forEach(item -> stringBuilder.append(item));//化簡(jiǎn)后IntStream.range(1, 101).forEach(stringBuilder::append);
調(diào)用構(gòu)造方法
官方給出的例子
先定義一個(gè)方法,這個(gè)方法的作用是將一個(gè)集合的內(nèi)容復(fù)制到另一個(gè)集合
public <T, SOURCE extends Collection<T>, DEST extends Collection<T>>DEST transferElements(SOURCE sourceCollection, Supplier<DEST> collectionFactory) { DEST result = collectionFactory.get(); result.addAll(sourceCollection); return result;}
調(diào)用這個(gè)方法
//化簡(jiǎn)前Set<Person> rosterSetLambda = transferElements(roster, () -> new HashSet<>());//化簡(jiǎn)后Set<Person> rosterSet = transferElements(roster, HashSet::new);
稍微解釋一下:
調(diào)用時(shí)傳入的Lambda表達(dá)式相當(dāng)于是對(duì)Supplier的繼承,并重寫Supplier的get()方法,下面是Supplier的源碼:
@FunctionalInterfacepublic interface Supplier<T> { /** * Gets a result. * * @return a result */ T get();}
在transferElements()方法中調(diào)用collectionFactory.get()時(shí)相當(dāng)于調(diào)用重寫后的方法{return new HashSet<>();}
我自己寫的一個(gè)例子
第一個(gè)類:
@Datapublic class ModelA { private String id; public ModelA(String id) { this.id = id; } public ModelA() { }}
第二個(gè)類
class ClassB { private final List<ModelA> list = new ArrayList<>(); public void add(String string, Function<String, ModelA> function) { list.add(function.apply(string)); }}
測(cè)試代碼
ClassB classB = new ClassB();d//化簡(jiǎn)前classB.add('ddd', item -> new ModelA(item));//化簡(jiǎn)后classB.add('ddd', ModelA::new);
調(diào)用的函數(shù)是參數(shù)item對(duì)象的方法且沒有參數(shù)時(shí)
//化簡(jiǎn)前List<String> stringList = list.stream().map(item -> item.getId()).collect(Collectors.toList());//化簡(jiǎn)后List<String> stringList = list.stream().map(ModelA::getId).collect(Collectors.toList());
一種特殊情況
除了上述兩種情況可以使用雙冒號(hào)化簡(jiǎn)Lambda表達(dá)式外,還存在一種特殊情況也可以使用雙冒號(hào)。當(dāng)Lambda表達(dá)式的參數(shù)有兩個(gè)(形如(a,b) -> an expression)時(shí),調(diào)用a的方法參數(shù)為b時(shí),例如:
String[] stringArray = {'Barbara', 'James', 'Mary', 'John'};//化簡(jiǎn)前Arrays.sort(stringArray, (a,b) -> a.compareToIgnoreCase(b));//化簡(jiǎn)后Arrays.sort(stringArray, String::compareToIgnoreCase);
到此這篇關(guān)于淺談對(duì)Java雙冒號(hào)::的理解的文章就介紹到這了,更多相關(guān)Java雙冒號(hào)::內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. idea打開多個(gè)窗口的操作方法2. IntelliJ IDEA 統(tǒng)一設(shè)置編碼為utf-8編碼的實(shí)現(xiàn)3. asp知識(shí)整理筆記4(問(wèn)答模式)4. 詳解idea中web.xml默認(rèn)版本問(wèn)題解決5. 解決ajax的delete、put方法接收不到參數(shù)的問(wèn)題方法6. IntelliJ IDEA 2020最新激活碼(親測(cè)有效,可激活至 2089 年)7. jsp EL表達(dá)式詳解8. java 優(yōu)雅關(guān)閉線程池的方案9. idea開啟代碼提示功能的方法步驟10. 使用Python爬取Json數(shù)據(jù)的示例代碼
