Java面向?qū)ο蠡A(chǔ)知識(shí)之委托和lambda
委托定義類型,類型指定特定方法簽名??蓪M足此簽名的方法(靜態(tài)或?qū)嵗┓峙浣o該類型的變量,然后(使用適當(dāng)參數(shù))直接調(diào)用該方法,或?qū)⑵渥鳛閰?shù)本身傳遞給另一方法再進(jìn)行調(diào)用。以下示例演示了委托的用法。
using System; using System.Linq; public class Program { public delegate string Reverse(string s); static string ReverseString(string s) { return new string(s.Reverse().ToArray()); } static void Main(string[] args) { Reverse rev = ReverseString; Console.WriteLine(rev("a string")); } }
public delegate string Reverse(string s);
行創(chuàng)建特定簽名的委托類型,在本例中即接受字符串參數(shù)并返回字符串參數(shù)的方法。static string ReverseString(string s)
方法與定義的委托類型具有完全相同的簽名,用于實(shí)現(xiàn)委托。Reverse rev = ReverseString;
行顯示可將方法分配給相應(yīng)委托類型的變量。Console.WriteLine(rev("a string"));
行演示如何使用委托類型的變量來調(diào)用委托。
為簡(jiǎn)化開發(fā)過程,.NET 包含一組委托類型,程序員可重用這些類型而無需創(chuàng)建新類型。其中包括Func<>
、Action<>
和Predicate<>
,可用于 .NET API 的各個(gè)位置,無需定義新委托類型。當(dāng)然,從這三者的簽名可以看出它們之間存在某些差異,主要影響其既定用途:
Action<>
用于需要使用委托參數(shù)執(zhí)行操作的情況。Func<>
通常用于現(xiàn)有轉(zhuǎn)換的情況,也就是說需要將委托參數(shù)轉(zhuǎn)換為其他結(jié)果時(shí)。最好的示例就是投影。Predicate<>
用于需要確定參數(shù)是否滿足委托條件的情況。也可將其寫作Func<T, bool>。
現(xiàn)在可使用Func<>委托而非自定義類型重新編寫上述示例。程序?qū)⒄张f繼續(xù)運(yùn)行。
using System; using System.Linq; public class Program { static string ReverseString(string s) { return new string(s.Reverse().ToArray()); } static void Main(string[] args) { Func<string, string> rev = ReverseString; Console.WriteLine(rev("a string")); } }
對(duì)于此簡(jiǎn)單示例而言,在Main方法之外定義方法似乎有些多余。因此 .NET Framework 2.0 引入了匿名委托的概念。在其支持下,可創(chuàng)建“內(nèi)聯(lián)”委托,而無需指定任何其他類型或方法。只需在所需位置內(nèi)聯(lián)委托的定義即可。
例如,要進(jìn)行切換并使用匿名委托篩選出只有偶數(shù)的列表,然后將其打印到控制臺(tái)。
using System; using System.Collections.Generic; public class Program { public static void Main(string[] args) { List<int> list = new List<int>(); for (int i = 1; i <= 100; i++) { list.Add(i); } List<int> result = list.FindAll( delegate (int no) { return (no % 2 == 0); } ); foreach (var item in result) { Console.WriteLine(item); } } }
如你所見,該委托的正文只是一組表達(dá)式,其他所有委托也是如此。但它并非單獨(dú)定義,而是在調(diào)用List<T>.FindAll方法時(shí)臨時(shí)引入。
但是,即使使用此方法,仍有許多可以丟棄的代碼。此時(shí)就需要使用lambda 表達(dá)式。
lambda 表達(dá)式(或簡(jiǎn)稱“l(fā)ambda”)在 C# 3.0 中作為語言集成查詢的 (LINQ) 核心構(gòu)建基塊被首次引入。這種表達(dá)式只是使用委托的更方便的語法。它們將聲明簽名和方法正文,但在分配到委托之前沒有自己的正式標(biāo)識(shí)。與委托不同,可將其作為事件注冊(cè)的左側(cè)內(nèi)容或在各種 LINQ 子句和方法中直接分配。
由于 lambda 表達(dá)式只是指定委托的另一種方式,因此應(yīng)可重新編寫上述示例,令其使用 lambda 表達(dá)式而不是匿名委托。
using System; using System.Collections.Generic; public class Program { public static void Main(string[] args) { List<int> list = new List<int>(); for (int i = 1; i <= 100; i++) { list.Add(i); } List<int> result = list.FindAll(i => i % 2 == 0); foreach (var item in result) { Console.WriteLine(item); } } }
在前面的示例中,所使用的 Lambda 表達(dá)式為i => i % 2 == 0。再次強(qiáng)調(diào),它只是使用委托的一種非常方便的語法,因此其實(shí)際行為與使用匿名委托時(shí)相同。
再次強(qiáng)調(diào),lambda 只是委托,這意味著可將其順利用作事件處理程序,如以下代碼片段所示。
public MainWindow() { InitializeComponent(); Loaded += (o, e) => { this.Title = "Loaded"; }; }
此上下文中的+=運(yùn)算符用于訂閱事件。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Springboot 接口對(duì)接文件及對(duì)象的操作方法
這篇文章主要介紹了Springboot 接口對(duì)接文件及對(duì)象的操作,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07解決Springboot項(xiàng)目報(bào)錯(cuò):java:錯(cuò)誤:不支持發(fā)行版本?17
這篇文章主要給大家介紹了關(guān)于解決Springboot項(xiàng)目報(bào)錯(cuò):java:錯(cuò)誤:不支持發(fā)行版本17的相關(guān)資料,這個(gè)錯(cuò)誤意味著你的Spring Boot項(xiàng)目正在使用Java 17這個(gè)版本,但是你的項(xiàng)目中未配置正確的Java版本,需要的朋友可以參考下2023-08-08Java實(shí)現(xiàn)批量修改文件名和重命名的方法
這篇文章主要介紹了Java實(shí)現(xiàn)批量修改文件名和重命名的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Myeclipse部署Tomcat_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章給大家介紹了Myeclipse部署Tomcat的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧2017-07-07java實(shí)現(xiàn)圖片上傳至本地實(shí)例詳解
我們給大家分享了關(guān)于java實(shí)現(xiàn)圖片上傳至本地的實(shí)例以及相關(guān)代碼,有需要的朋友參考下。2018-08-08