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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...