日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

λ表达式_Java 8新特性:学习如何使用Lambda表达式,一看必懂

發(fā)布時(shí)間:2023/12/19 java 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 λ表达式_Java 8新特性:学习如何使用Lambda表达式,一看必懂 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我將分為兩篇系列文章來(lái)描述了使用Java 8的新特性 - lambda表達(dá)式。

目錄

  • 介紹
  • 我們?yōu)槭裁葱枰猯ambdas?
  • Lambdas的語(yǔ)法
  • 功能接口
  • 方法參考
  • 構(gòu)造函數(shù)參考
  • 可變范圍
  • 默認(rèn)方法
  • 結(jié)論

介紹

Java 8版本是當(dāng)前java界流行最廣的一個(gè)版本。它的主要改進(jìn)是在面向?qū)ο蟮幕A(chǔ)上增加了對(duì)函數(shù)式編程的支持。在本文中,我將展示lambda的基本語(yǔ)法,并闡釋幾種適用的上下文環(huán)境。

我們?yōu)槭裁葱枰猯ambdas?

lambda表達(dá)式是一個(gè)可以傳遞的代碼塊,允許您稍后執(zhí)行它,只執(zhí)行一次或多次。說到這里,你可能感覺似曾相識(shí),看下面的這段業(yè)務(wù)場(chǎng)景:

我們經(jīng)常自定義比較器來(lái)進(jìn)行集合排序。比如現(xiàn)在要按字符串長(zhǎng)度對(duì)字符串進(jìn)行排序,通常做法是自定義一個(gè) Comparator對(duì)象并傳遞給方法進(jìn)行排序,如下:

我們編寫了一段用于比較元素的代碼片段,封裝在自定義的Comparator里。Arrays.sort方法會(huì)在適當(dāng)時(shí)機(jī)調(diào)用此代碼片段,對(duì)strings數(shù)組進(jìn)行排序。

那么,這個(gè)適當(dāng)時(shí)機(jī),是什么時(shí)候呢?它可能是某個(gè)界面上的一個(gè)按鈕被點(diǎn)擊時(shí),也可能是某個(gè)新線程被啟動(dòng)時(shí),像下面doWork方法被調(diào)用時(shí):

于是,當(dāng)我們想要執(zhí)行此代碼時(shí),就實(shí)例化一個(gè) MyRunner對(duì)象。然后,把實(shí)例放入線程池,或者只是啟動(dòng)一個(gè)新線程:

總結(jié)一下整個(gè)場(chǎng)景:我把一段代碼塊傳遞給某人 - 線程池,排序方法或按鈕。希望在適當(dāng)時(shí)機(jī)需要時(shí),他們調(diào)用我這段代碼來(lái)進(jìn)行排序。

在java8以前,想要傳遞代碼塊很不容易。我們只能把代碼塊寫在一個(gè)特殊類里,然后實(shí)例化一個(gè)類對(duì)象來(lái)傳遞這段代碼。

在其他語(yǔ)言中,例如C#,則可以直接使用代碼塊。java語(yǔ)言設(shè)計(jì)者多年來(lái)一直反對(duì)添加此功能。理由無(wú)非是想要保持語(yǔ)法的簡(jiǎn)單性和一致性。但卻犧牲了編碼便利性。

在下一節(jié)中,我們一起來(lái)了解如何在Java中使用代碼塊。

Lambdas的語(yǔ)法

讓我們?cè)俅位氐阶址判颉N覀兲峁┝舜_定哪個(gè)字符串更短的代碼。我們計(jì)算

這一行代碼無(wú)非表達(dá)了一個(gè)意思,使用Integer.compare對(duì) firstStr和 secondStr進(jìn)入排序。

讓我們用提問的方式來(lái)更明確的描述這個(gè)意思:

1、我們要處理的入?yún)?shù)數(shù)據(jù)是什么?是什么數(shù)據(jù)類型?

2、使用什么代碼片斷來(lái)對(duì)它們進(jìn)行處理?

有了提問,回答就容易了。是對(duì)這樣的入?yún)?shù)據(jù)進(jìn)行處理(String firstStr, String secondStr),使用這樣的 Integer.compare(firstStr.length(),secondStr.length()) 代碼片斷。

于是,有了我們第一個(gè)lambda表達(dá)式!此表達(dá)式指定代碼塊和必須傳遞給代碼塊的變量。

還有一點(diǎn)歷史...關(guān)于lambda這個(gè)名字的來(lái)歷?很久以前,在計(jì)算機(jī)還沒有出世的時(shí)候,數(shù)學(xué)家Alonzo Church想要形式化數(shù)學(xué)函數(shù)有效計(jì)算的意義。(有一些已知存在的函數(shù),但沒有人知道如何計(jì)算它們的值。)他使用希臘符號(hào)lambda(λ)來(lái)標(biāo)記參數(shù)。從那以后,帶有參數(shù)變量的表達(dá)式被稱為“l(fā)ambda表達(dá)式”。

Java lambda略有幾種不同的形式。讓我們更仔細(xì)地考慮一下。您剛剛看到其中一個(gè):參數(shù), - >箭頭和表達(dá)式。如果代碼包含的計(jì)算不適合單個(gè)表達(dá)式,那么就像編寫方法一樣編寫它:將代碼放入{}并添加顯式 return語(yǔ)句。例如,

如果lambda中沒有參數(shù),你仍然應(yīng)該放置空括號(hào),就像無(wú)參數(shù)方法一樣:

如果可以推斷l(xiāng)ambda的參數(shù)類型,則可以省略它們。例如,

此時(shí),編譯器可以找出 firstStr并且 secondStr是字符串,因?yàn)槲覀儗ambda分配給字符串比較器。(我們稍后會(huì)仔細(xì)研究這段代碼。)

如果一個(gè)方法只有一個(gè)參數(shù),編譯器可以推導(dǎo)出是哪種類型,你甚至可以省略括號(hào):

此外,您可以像 final方法參數(shù)一樣,將修飾符和注釋放在lambda參數(shù)中:

您永遠(yuǎn)不需要指定lambda表達(dá)式的結(jié)果類型。編譯器總是從上下文中推斷出它。例如,您可以使用lambda

其中 int預(yù)期作為結(jié)果類型。

請(qǐng)注意,在lambda中,您不能返回不在分支中的值。例如, (intx)->{if(x<=1)return-1;}無(wú)效。

功能接口

像我們文章開頭討論的那樣,Java可以借用接口來(lái)封裝代碼塊,比如 Runnable或 Comparator。這對(duì)Lambdas同樣適用。

在Java中有所謂的功能接口 - 一個(gè)只有單個(gè)抽象方法實(shí)現(xiàn)的接口對(duì)象。只要需要功能接口的對(duì)象,就可以使用lambda表達(dá)式。

讓我們考慮一下 Arrays.sort方法的例子。在這里我們可以看到用lambda替換功能接口。我們只是將lambda作為第二個(gè)參數(shù)傳遞給方法,該參數(shù)需要一個(gè) Comparator對(duì)象,該接口只有一個(gè)方法。

實(shí)際上該 Arrays.sort方法接收一些類實(shí)現(xiàn)的對(duì)象 Comparator。compare調(diào)用該方法時(shí),它會(huì)強(qiáng)制執(zhí)行l(wèi)ambda表達(dá)式主體。這些對(duì)象和類的結(jié)構(gòu)完全取決于實(shí)現(xiàn)。它不僅可以使用傳統(tǒng)的內(nèi)部類。也許最好將lambda表示為一個(gè)函數(shù),而不是作為一個(gè)對(duì)象,并發(fā)現(xiàn)我們可以將它傳遞給一個(gè)功能接口。

這種對(duì)接口的轉(zhuǎn)換是lambda表達(dá)式令人興奮的原因。語(yǔ)法簡(jiǎn)短。這是另一個(gè)例子:

是不是很易讀?

事實(shí)上,你在Java中使用lambda表達(dá)式唯一能做的就是轉(zhuǎn)換。

Java API中的java.util.function包中有幾個(gè)通用的功能接口。其中之一, BiFunction代表與參數(shù)類型的函數(shù) T和 U和返回類型 R。您可以將字符串比較lambda傳給這樣的變量:

您可以在不同的Java 8 API中看到j(luò)ava.util.function中的這些接口。在Java 8中,任何功能接口都可以用@FunctionalInterface。這個(gè)注釋是可選的,但卻是一個(gè)很好的風(fēng)格。首先,它強(qiáng)制編譯器檢查帶注釋的實(shí)體是否是具有單個(gè)抽象方法的接口。第二是告訴javadoc頁(yè)面包含一個(gè)聲明,這個(gè)接口是一個(gè)功能接口。根據(jù)定義,任何只有一個(gè)抽象方法的接口都是一個(gè)功能接口。但是,使用此關(guān)鍵字可以更加清晰。

順便說一句,在將lambda轉(zhuǎn)換為功能接口時(shí),可能會(huì)出現(xiàn)已檢查的異常。如果lambda表達(dá)式的主體拋出已檢查的異常,則應(yīng)在目標(biāo)接口的抽象方法中聲明此異常。例如,以下代碼將導(dǎo)致錯(cuò)誤:

此語(yǔ)句不正確,因?yàn)樵?run方法不能拋出任何異常。有兩種方法應(yīng)對(duì)此問題。

一種方法是捕獲lambda體中的異常。第二個(gè)是將此lambda分配給具有單個(gè)抽象方法的接口,該方法可以拋出異常。例如, call接口的方法 Callable可以生成任何異常。因此,如果 returnnull在lambda主體的末尾添加,則可以將lambda分配給 Callable實(shí)例。

對(duì)以上有任何疑問的都可以留言評(píng)論~

讀者福利:分享一大波面試題給大家,需要的自行點(diǎn)擊鏈接閱讀哦!

Java面試必刷真題200+,讓你“過五關(guān),斬六將”,輕松入大廠

總結(jié)

以上是生活随笔為你收集整理的λ表达式_Java 8新特性:学习如何使用Lambda表达式,一看必懂的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。