在上一篇文章中我們介紹了JDK1.8的新特性有以下幾項,
1.Lambda運算式
2.方法參考
3.函式式介面
4.默認方法
5.Stream
6.Optional類
7.Nashorm javascript引擎
8.新的日期時間API
9.Base64
并且學習了JDK1.8最重要的特性--Lambda運算式,這一篇學習方法參考,
首先介紹方法參考是啥?
方法參考單從“參考”二字不難理解,我們經常拿毛主席的”不管黑貓白貓能抓住老鼠的貓就是好貓“這句話來說事情,這里就是參考了毛主席的話,那么方法參考就是拿過其他地方已經存在的方法,我們拿過來使用,在這里可以理解成Lambda運算式的一種特殊用法,只是我們得按照一定的規則來用,也就是我們接下來要重點要學習的內容:方法參考的方式
接下來先列出方法參考的方式,
總體來說方法參考有三種方式,分別如下,
1.普通方法參考
1.1 實體方法參考(通過實體物件)
物件::實體方法名;
1.2 靜態方法參考
類名::靜態方法名;
1.3 實體方法參考(通過類名)
類名::實體方法名;
注:上面兩種實體方法參考的不同之處,通過下面代碼詳細說明,
2.構造器參考
類名::new;
3.陣列參考
型別::new;
下面重點通過實體來學習上面的集中形式,
1.1 實體方法參考(通過實體物件)
下面通過最簡單的列印輸出陳述句來理解實體方法參考,
1 public class MethodReferenceTest { 2 3 /** 4 * 為了更容易理解方法參考 5 * 我通過正常的Lambda運算式和方法參考兩種方式來實作代碼部分 6 */ 7 //***************************** 8 // 方法參考的形式一 物件::實體方法名 9 //***************************** 10 @Test 11 public void test1(){ 12 //Lambda運算式 13 PrintStream ps1 = System.out; 14 Consumer con1 = x -> ps1.println(x); 15 con1.accept("Hello Lambda運算式!"); 16 17 //方法參考 18 PrintStream ps2 = System.out; 19 Consumer con2 = ps2::println; 20 con2.accept("Hello 方法參考!"); 21 } 22 23 }
執行結果
...
com.dream.test.JDK8speciality.MethodReferenceTest,test1
Hello Lambda運算式!
Hello 方法參考!
Process finished with exit code 0
通過上面實體14行和19行的對比可以看出,使用方法參考的方式比直接Lambda運算式更簡潔,再次也可以看做方法參考是Lambda運算式的一種特殊寫法,學習了Lambda運算式,方法參考的寫法也就不難理解了,
注:Consumer是JDK1.8的java.util.function包下提供的一個函式式介面,accept方法接收一個泛型<T>型別,回傳值為void的抽象方法,具體實作是Lambda運算式的部分去實作的,也就是 x -> ps1.println(x); 和 ps2::println; 關于JDK1.8提供的函式式介面會在后面函式式介面章節進行學習,
1.2 靜態方法參考
下面通過比較兩個整數的大小來理解靜態方法的參考,
1 public class MethodReferenceTest { 2 3 //***************************** 4 // 方法參考的形式二 類名::靜態方法名 5 //***************************** 6 @Test 7 public void test2(){ 8 //Lambda運算式 9 //x > y:回傳1; 10 //x = y:回傳0; 11 //x < y:回傳-1; 12 Comparator<Integer> com1 = (x,y)->Integer.compare(x,y); 13 Integer i1=com1.compare(2,1); 14 System.out.println("Lambda運算式結果:" + i1); 15 16 //方法參考 17 Comparator<Integer> com2 = Integer::compare; 18 Integer i2=com2.compare(2,1); 19 System.out.println("方法參考結果:" + i2); 20 } 21 22 }
執行結果
com.dream.test.JDK8speciality.MethodReferenceTest,test2
Lambda運算式結果:1
方法參考結果:1
Process finished with exit code 0
正常通過Lam運算式我們 (x,y)->Integer.compare(x,y);這樣寫,由于Integer類下有靜態方法已經實作了兩個整數的比較,所有我們通過靜態方法參考的方式直接參考就好了,由此變成了Integer::compare;
1.3 實體方法參考(通過類名)
通過比較兩個字串的內容來說明,
1 public class MethodReferenceTest { 2 3 //***************************** 4 // 方法參考的形式三 類名::實體方法 5 //***************************** 6 @Test 7 public void test3(){ 8 //比較兩個字串的內容 9 //Lambda運算式 10 BiPredicate<String,String> bp1 = (s1,s2) -> s1.equals(s2); 11 boolean b1 = bp1.test("abc","abc"); 12 System.out.println("Lambda結果:" + b1); 13 14 //方法參考 15 BiPredicate<String,String> bp2 = String::equals; 16 boolean b2 = bp2.test("abc","abc"); 17 System.out.println("方法結果:" + b2); 18 } 19 20 }
執行結果
...
com.dream.test.JDK8speciality.MethodReferenceTest,test3 Lambda結果:true 方法結果:true Process finished with exit code 0
通過物件的方式參考和通過類名的方式參考不同之處是:當函式式引數串列的第一個引數是方法的呼叫者,而且第二個引數是被呼叫方法的引數的時候,我們就需要用【類名::方法名】的方式來書寫代碼,
這里的BiPredicate也是JDK1.8的java.util.function包下的函式是介面,關于函式式介面會在后面函式式介面章節進行學習,在這里知道它是函式介面介面即可,
2.構造器參考
由于構造器是創建物件的時候使用的所以這里也是要用new關鍵字的,也就是【類名::new】的形式,
1 public class MethodReferenceTest { 2 //***************************** 3 // 構造器參考 類名::實體方法 4 //***************************** 5 @Test 6 public void test4(){ 7 //通過無引數的構造器創建物件 8 System.out.println("無參構造器"); 9 //Lambda運算式 10 System.out.println("Lambda運算式:"); 11 Supplier<User> su1 =() -> new User();//Lambda運算式沒有引數的時候圓括號不可省略 12 User user1 = su1.get(); 13 System.out.println("userName:" + user1.getUserName() + " pwd:" + user1.getPwd()); 14 15 //構造器參考 16 System.out.println("構造器參考:"); 17 Supplier<User> su2 = User::new; 18 User user2 = su2.get(); 19 System.out.println("userName:" + user2.getUserName() + " pwd:" + user2.getPwd()); 20 21 //通過有引數的構造器創建物件 22 System.out.println("有引數構造器"); 23 //Lambda運算式 24 System.out.println("Lambda運算式:"); 25 BiFunction<String,String,User> bf1 = (userName,pwd) -> new User(userName,pwd); 26 User user3 = bf1.apply("[email protected]","987654321"); 27 System.out.println("userName:" + user3.getUserName() + " pwd:" + user3.getPwd()); 28 29 //構造器參考 30 System.out.println("構造器參考:"); 31 BiFunction<String,String,User> bf2 = User::new; 32 User user4 = bf2.apply("[email protected]","987654321"); 33 System.out.println("userName:" + user4.getUserName() + " pwd:" + user4.getPwd()); 34 35 /** 36 * 通過對以上有引數,無引數的構造器參考的實體可以看出: 37 * 無論構造器引數有幾個,參考部分的代碼都是ClassName::new,不同的是函式式介面, 38 */ 39 } 40 41 }
執行結果
...
com.dream.test.JDK8speciality.MethodReferenceTest,test4 無參構造器 Lambda運算式: userName:null pwd:null 構造器參考: userName:null pwd:null 有引數構造器 Lambda運算式: userName:[email protected] pwd:987654321 構造器參考: userName:[email protected] pwd:987654321 Process finished with exit code 0
有了前面幾個方法參考的了解這里也就不難理解,只要記住構造方法參考的形式即可,需要注意的是:當Lambda運算式的沒有引數的時候必須寫上【() -> 】不能省略,否則報錯,
還有一個需要注意的點就是,無論構造器有幾個引數,構造器參考的形式都是【類名::構造器名】,變化的使用的函式式介面不同而已,關于函式式介面詳細會在后面函式式介面章節進行學習,
3.陣列參考
陣列參考的形式和構造器參考的形式類似只是變成了【類名[]::構造器名】而已,也不用做過多解釋,直接看例子即可,
1 public class MethodReferenceTest { 2 3 //***************************** 4 // 陣列參考 型別::new 5 //***************************** 6 @Test 7 public void test5(){ 8 //Lambda運算式 9 Function<Integer,Integer[]> f1 =i -> new Integer[i]; 10 Integer[] iArray1 = f1.apply(10); 11 System.out.println("Lambda運算式:Array長度為" + iArray1.length); 12 13 //陣列參考 14 Function<Integer,Integer[]> f2 =Integer[]::new; 15 Integer[] iArray2 = f2.apply(10); 16 System.out.println("陣列參考:Array長度為" + iArray2.length); 17 } 18 19 }
執行結果
...
com.dream.test.JDK8speciality.MethodReferenceTest,test5
Lambda運算式:Array長度為10
陣列參考:Array長度為10
Process finished with exit code 0
這里使用了Function函式式介面,也會在接下來的文章中解釋,
以上就是我對于方法參考的理解,如果有理解錯誤或者寫的不好的地方還請各位大神不吝賜教呀,歡迎指正,
上一篇文章
JDK1.8新特性之(一)--Lambda運算式
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/186214.html
標籤:Java
上一篇:第六章第三十二題(游戲:贏取雙骰子賭博游戲的機會)(Game: chance of winning at craps) - 編程練習題答案
