λ表达式_Java 8新特性:学习如何使用Lambda表达式,一看必懂
我將分為兩篇系列文章來描述了使用Java 8的新特性 - lambda表達式。
目錄
- 介紹
- 我們為什么需要lambdas?
- Lambdas的語法
- 功能接口
- 方法參考
- 構造函數參考
- 可變范圍
- 默認方法
- 結論
介紹
Java 8版本是當前java界流行最廣的一個版本。它的主要改進是在面向對象的基礎上增加了對函數式編程的支持。在本文中,我將展示lambda的基本語法,并闡釋幾種適用的上下文環境。
我們為什么需要lambdas?
lambda表達式是一個可以傳遞的代碼塊,允許您稍后執行它,只執行一次或多次。說到這里,你可能感覺似曾相識,看下面的這段業務場景:
我們經常自定義比較器來進行集合排序。比如現在要按字符串長度對字符串進行排序,通常做法是自定義一個 Comparator對象并傳遞給方法進行排序,如下:
我們編寫了一段用于比較元素的代碼片段,封裝在自定義的Comparator里。Arrays.sort方法會在適當時機調用此代碼片段,對strings數組進行排序。
那么,這個適當時機,是什么時候呢?它可能是某個界面上的一個按鈕被點擊時,也可能是某個新線程被啟動時,像下面doWork方法被調用時:
于是,當我們想要執行此代碼時,就實例化一個 MyRunner對象。然后,把實例放入線程池,或者只是啟動一個新線程:
總結一下整個場景:我把一段代碼塊傳遞給某人 - 線程池,排序方法或按鈕。希望在適當時機需要時,他們調用我這段代碼來進行排序。
在java8以前,想要傳遞代碼塊很不容易。我們只能把代碼塊寫在一個特殊類里,然后實例化一個類對象來傳遞這段代碼。
在其他語言中,例如C#,則可以直接使用代碼塊。java語言設計者多年來一直反對添加此功能。理由無非是想要保持語法的簡單性和一致性。但卻犧牲了編碼便利性。
在下一節中,我們一起來了解如何在Java中使用代碼塊。
Lambdas的語法
讓我們再次回到字符串排序。我們提供了確定哪個字符串更短的代碼。我們計算
這一行代碼無非表達了一個意思,使用Integer.compare對 firstStr和 secondStr進入排序。
讓我們用提問的方式來更明確的描述這個意思:
1、我們要處理的入參數數據是什么?是什么數據類型?
2、使用什么代碼片斷來對它們進行處理?
有了提問,回答就容易了。是對這樣的入參數據進行處理(String firstStr, String secondStr),使用這樣的 Integer.compare(firstStr.length(),secondStr.length()) 代碼片斷。
于是,有了我們第一個lambda表達式!此表達式指定代碼塊和必須傳遞給代碼塊的變量。
還有一點歷史...關于lambda這個名字的來歷?很久以前,在計算機還沒有出世的時候,數學家Alonzo Church想要形式化數學函數有效計算的意義。(有一些已知存在的函數,但沒有人知道如何計算它們的值。)他使用希臘符號lambda(λ)來標記參數。從那以后,帶有參數變量的表達式被稱為“lambda表達式”。
Java lambda略有幾種不同的形式。讓我們更仔細地考慮一下。您剛剛看到其中一個:參數, - >箭頭和表達式。如果代碼包含的計算不適合單個表達式,那么就像編寫方法一樣編寫它:將代碼放入{}并添加顯式 return語句。例如,
如果lambda中沒有參數,你仍然應該放置空括號,就像無參數方法一樣:
如果可以推斷lambda的參數類型,則可以省略它們。例如,
此時,編譯器可以找出 firstStr并且 secondStr是字符串,因為我們將lambda分配給字符串比較器。(我們稍后會仔細研究這段代碼。)
如果一個方法只有一個參數,編譯器可以推導出是哪種類型,你甚至可以省略括號:
此外,您可以像 final方法參數一樣,將修飾符和注釋放在lambda參數中:
您永遠不需要指定lambda表達式的結果類型。編譯器總是從上下文中推斷出它。例如,您可以使用lambda
其中 int預期作為結果類型。
請注意,在lambda中,您不能返回不在分支中的值。例如, (intx)->{if(x<=1)return-1;}無效。
功能接口
像我們文章開頭討論的那樣,Java可以借用接口來封裝代碼塊,比如 Runnable或 Comparator。這對Lambdas同樣適用。
在Java中有所謂的功能接口 - 一個只有單個抽象方法實現的接口對象。只要需要功能接口的對象,就可以使用lambda表達式。
讓我們考慮一下 Arrays.sort方法的例子。在這里我們可以看到用lambda替換功能接口。我們只是將lambda作為第二個參數傳遞給方法,該參數需要一個 Comparator對象,該接口只有一個方法。
實際上該 Arrays.sort方法接收一些類實現的對象 Comparator。compare調用該方法時,它會強制執行lambda表達式主體。這些對象和類的結構完全取決于實現。它不僅可以使用傳統的內部類。也許最好將lambda表示為一個函數,而不是作為一個對象,并發現我們可以將它傳遞給一個功能接口。
這種對接口的轉換是lambda表達式令人興奮的原因。語法簡短。這是另一個例子:
是不是很易讀?
事實上,你在Java中使用lambda表達式唯一能做的就是轉換。
Java API中的java.util.function包中有幾個通用的功能接口。其中之一, BiFunction代表與參數類型的函數 T和 U和返回類型 R。您可以將字符串比較lambda傳給這樣的變量:
您可以在不同的Java 8 API中看到java.util.function中的這些接口。在Java 8中,任何功能接口都可以用@FunctionalInterface。這個注釋是可選的,但卻是一個很好的風格。首先,它強制編譯器檢查帶注釋的實體是否是具有單個抽象方法的接口。第二是告訴javadoc頁面包含一個聲明,這個接口是一個功能接口。根據定義,任何只有一個抽象方法的接口都是一個功能接口。但是,使用此關鍵字可以更加清晰。
順便說一句,在將lambda轉換為功能接口時,可能會出現已檢查的異常。如果lambda表達式的主體拋出已檢查的異常,則應在目標接口的抽象方法中聲明此異常。例如,以下代碼將導致錯誤:
此語句不正確,因為該 run方法不能拋出任何異常。有兩種方法應對此問題。
一種方法是捕獲lambda體中的異常。第二個是將此lambda分配給具有單個抽象方法的接口,該方法可以拋出異常。例如, call接口的方法 Callable可以生成任何異常。因此,如果 returnnull在lambda主體的末尾添加,則可以將lambda分配給 Callable實例。
對以上有任何疑問的都可以留言評論~讀者福利:分享一大波面試題給大家,需要的自行點擊鏈接閱讀哦!
Java面試必刷真題200+,讓你“過五關,斬六將”,輕松入大廠
總結
以上是生活随笔為你收集整理的λ表达式_Java 8新特性:学习如何使用Lambda表达式,一看必懂的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 4 月 4 日发布,消息称一加 Nord
- 下一篇: Keep发布健身新物种“KS”,引领智能
