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
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...