JDK1.8新特性之(二)--方法引用

来源:https://www.cnblogs.com/worthycoder/archive/2020/05/21/12932684.html
-Advertisement-
Play Games

在上一篇文章中我們介紹了JDK1.8的新特性有以下幾項。 1.Lambda表達式 2.方法引用 3.函數式介面 4.預設方法 5.Stream 6.Optional類 7.Nashorm javascript引擎 8.新的日期時間API 9.Base64 並且學習了JDK1.8最重要的特性--Lam ...


在上一篇文章中我們介紹了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表達式


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、電腦要完成兩數相加,可以大致分為如下幾個步驟: 1.從記憶體位置2000上把一個數字拷貝到寄存器1; 2.從記憶體位置2004上把另一個數字拷貝到寄存器2; 3.把寄存器2裡面的內容與寄存器1中的內容相加,把結果儲存在寄存器1中。 4.把寄存器1中的內容拷貝到記憶體位置2008。 二、高級語言以更抽 ...
  • 今天是521,就分享一個程式員必會的——情侶回憶殺《愛情電子相冊》吧!話不多說,先上思路,後接源碼! 具備能力: 1.基本可視化編程 1.1 initgraph(800,600); 1.2 關閉視窗closegraph(); 1.3 視窗坐標 2.基本繪圖函數 2.1 line 畫線 2.2 cir ...
  • Level 7kyu :Two to One 取2個字元串s1,s2僅包含從a到的字母z。 返回一個新的排序字元串,最長的字元串,包含不同的字母, 每個僅取一次-來自s1或s2。 主要方法: toCharArray()->字元串轉字元數組 arraycopy(from,0,to,0,長度)->複製數 ...
  • Level 7kyu :Get the Middle Character 您將得到一個單詞。 您的工作是返回單詞的中間字元。 要求: 如果單詞的長度是奇數,則返回中間字元。 如果單詞的長度是偶數,請返回中間的2個字元。 主要方法: length()->獲取字元串長度 charAt(索引下標)->返回 ...
  • manacher 線性查找演算法 manacher演算法中需要知道的概念: 迴文半徑: 迴文中心 到 迴文邊界的距離. 迴文半徑數組: radius[i]表示以 i 為迴文中心的最大迴文半徑. 迴文最右邊界: 出現的迴文邊界中最右的位置. 首次迴文中心: 迴文最右邊界首次出現時的迴文中心. 首次迴文左邊 ...
  • 1. PIL Image圖片顯示 在使用PIL函數中的Image方法讀取圖片時,對於圖片的shape,可能有不少寶寶存在疑惑。是什麼疑惑了?就是image = Image.open(image_path),當你執行print(image.size)時,你得到的是圖片的真實維度:W * H(寬和高), ...
  • Token驗證是驗證用戶身份的重要方式,在golang開發中具有廣泛應用,文中主要闡述了利用jwt包加密後的token驗證。 導入包: import ( "github.com/dgrijalva/jwt-go") // GenerateToken 生成Tokenfunc GenerateToken ...
  • 準備鏡像 我使用的centos系統,docker-ce最新版本。 先準備好三個鏡像 docker pull mysql:5.7 docker pull php:5.6-fpm docker pull nginx:latest 註意,mysql和php不要使用最新版本,坑很多。 docker imag ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...