1.說明
之前沒用過::這個東西,今天看flink的時候發現官網有個例子用到了這個符號, 本著求知欲去百度查了一番,沒找到能說到我心里去的解釋,本著求知欲的態度,我去了官網看了看. java ::
2.先來說下@FunctionalInterface
java8 lambda 內部接口需要@FunctionalInterface這個注解,這個注解是一個說明性質的注解,被@FunctionalInterface注解的接口只能由一個抽象方法,@FunctionalInterface只能用于注解接口而不能用在class以及枚舉上.
被@FunctionalInterface注解的符合規則的接口,可以用lambda表達式. 下面舉一個例子:
1
2
3
4
5
6
7
8
9
10
11
|
public class Main { public static void pr(String s){ System.out.println(s); } public static void main(String[] args) throws Exception { List<String> list = Arrays.asList( "aaaa" , "bbbb" , "cccc" ); list.forEach(s -> System.out.println(s)); } } |
所以說,@FunctionalInterface用于lambda樣式說明.
3. 下面來講講這個 "::"是干嘛的
"::"官網對這個符號的解釋是方法引用,也就是引用一個方法的意思,英文名稱Method References
lambda expressions 可以用來創建一匿名的方法, 這個匿名的方式你需要自己實現.
1
2
3
4
5
6
7
|
1 . list.forEach( new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }); 2 . list.forEach(s -> System.out.println(s)); |
上面兩種寫法是一樣的,下面就是lambda表達式.
上面說了lambda表達式你需要自己實現,但是有些時候這不是必要的,比如你的項目里某個地方存在了一個符合當前邏輯的lambda表達式的方法, 那么我是否可以直接拿來用?, 答案是可以, 程序追求的就是不重復極簡的思想, 既有則拿來用即可,為什么還要自己實現呢. Method References 就是用來做這件事的.
在看下面的例子之前讀者需要知道java 比較器,否則看不懂代碼.
4. 建立一個Person類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public class Person implements Comparable<Person>{ public String name; public int age; @Override public String toString() { return "Person{" + "name='" + name + '\ '' + ", age=" + age + '}' ; } public Person(String name, int age) { this .name = name; this .age = age; } public static int compareByAge(Person a, Person b) { return a.compareTo(b); } @Override public int compareTo(Person o) { if ( this .age > o.age){ return - 1 ; } else { return 1 ; } } } |
4:構建多個person對象,放入數組中,然后對數組中的person重新排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class Test { //編寫Comparator,Person的age private static final Comparator<Person> COMPARATOR = new Comparator<Person>() { public int compare(Person a, Person b) { return a.compareTo(b); //運用User類的compareTo方法比較兩個對象 } }; public static void main(String[] args) { Person one = new Person( "張三" , 50 ); Person two = new Person( "李四" , 100 ); ArrayList<Person> array = new ArrayList<>(); array.add(one); array.add(two); Collections.sort(array,COMPARATOR); System.out.println(array); } } //輸出結果: //[Person{name='李四', age=100} //Person{name='張三', age=50}] |
仔細看上面的代碼,重點在Collections.sort(array,COMPARATOR);這一行,sort接收兩個參數,第一個是要被排序的數組,第二個是一個比較器對象Comparator,其源碼如下,我只粘貼了必要的部分.
1
2
3
4
|
** @FunctionalInterface ** public interface Comparator<T> { int compare(T o1, T o2); } |
@FunctionalInterface我們知道,被這個注解修飾的接口可以用lambda表達式的.
所以我們將class Test改成下面的樣子:
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Test { public static void main(String[] args) { Person one = new Person( "張三" , 50 ); Person two = new Person( "李四" , 100 ); ArrayList<Person> array = new ArrayList<>(); array.add(one); array.add(two); Collections.sort(array, (a, b) -> a.compareTo(b)); System.out.println(array); } } |
注意:下面是lambda寫法,和正常傳統寫法
1
2
3
4
5
6
7
8
|
Collections.sort(array, (a, b) -> a.compareTo(b)); 和下面的等效 Collections.sort(array, new Comparator() { @Override public int compare(Person a, Person b) { return a.compareTo(b); } }); |
5:揭秘 "::"符號
到這里其實我們上面的功能已經完成了,我們來分析一下代碼.
1:構造了兩個對象
2:把對象放入了數組
3:Collection.sort(array,Comparator<T>) 對數組進行排序
關鍵點在于:Comparator<T> 比較器,它是一個被@FunctionalInterface修飾的接口,我們一般成為函數式接口.
因此,Collection.sort(array,Comparator<T>) ,對于第二個參數Comparator<T>,我們可以傳入一個匿名實現類,然后實現里面的 int compare(T o1, T o2) 方法,也可以寫成lambda表達式的樣子,到這里如果你都懂了,那么接下來就好說了,如果沒明白,回頭接著看,相信自己騷年. 下面我們重點看lambda方式的寫法,這和"::"息息相關
Collections.sort(array, (a, b) -> a.compareTo(b));
- **(a, b) -> a.compareTo(b)**這個其實就是匿名函數, 該函數的參數分別是Person a, Person b
- a.compareTo(b) 是該匿名函數的邏輯,
也即是說我們寫出來的這個匿名函數有兩個參數,以及一個調用compareTo的函數體,到這里其實結束了,一開始我們就說了,符號"::"的意義就是用一個已經存在的函數代替我們lambda表達式中的函數體,只要這個存在的函數和lambda函數體的函數格式一致就行了. 格式其實就是參數個數,和參數類型下面是新的class Test揭示了答案
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Test { public static void main(String[] args) { Person one = new Person( "張三" , 50 ); Person two = new Person( "李四" , 100 ); ArrayList<Person> array = new ArrayList<>(); array.add(one); array.add(two); Collections.sort(array, Person::compareByAge); //寫法一 // Collections.sort(array, one::entyMethod);//寫法二 System.out.println(array); } } |
附官網的一句話:
Because this lambda expression
invokes an existing method,
you can use a method reference
**instead of** a lambda expression
1
2
|
Collections.sort(array, Person::compareByAge); Collections.sort(array, one::entyMethod); |
這兩種寫法都是可行的.
6.0 方法引用的支持如下
我們上面講了靜態方法,和類方法的代替方式,至于其他的這里不講了,主要是我要去吃飯了.
到此這篇關于Java雙冒號(::)運算符使用詳解的文章就介紹到這了,更多相關Java雙冒號(::)內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/qq_36066039/article/details/120225882