第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Lambda 表達(dá)式的變量與作用域

本節(jié)我們將分析 Lambda 表達(dá)式的局部變量及其作用域進(jìn)行分析,在這基礎(chǔ)上我們會(huì)探討其訪問(wèn)規(guī)則背后的原因。

在開(kāi)始之前我們需要明確一句話:

引用值,而不是變量!

引用值,而不是變量!

引用值,而不是變量!

重要的事情說(shuō)三遍?。?!

1. 訪問(wèn)局部變量

Lambda 表達(dá)式不會(huì)從父類(lèi)中繼承任何變量名,也不會(huì)引入一個(gè)新的作用域。Lambda 表達(dá)式基于詞法作用域,也就是說(shuō) Lambda 表達(dá)式函數(shù)體里面的變量和它外部環(huán)境的變量具有相同的語(yǔ)義。

訪問(wèn)局部變量要注意如下 3 點(diǎn):

  1. 可以直接在 Lambda 表達(dá)式中訪問(wèn)外層的局部變量;
  2. 在 Lambda 表達(dá)式當(dāng)中被引用的變量的值不可以被更改;
  3. 在 Lambda 表達(dá)式當(dāng)中不允許聲明一個(gè)與局部變量同名的參數(shù)或者局部變量。

現(xiàn)在我們來(lái)仔細(xì)說(shuō)明下這三點(diǎn)。

1.1 可以直接在 Lambda 表達(dá)式中訪問(wèn)外層的局部變量

在 Lambda 表達(dá)式中可以直接訪問(wèn)外層的局部變量,但是這個(gè)局部變量必須是聲明為 final 的。

首先我們來(lái)看一個(gè)例子:

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
import java.util.function.BinaryOperator;

public class LambdaTest1 {

    public static void main(String[] args) {
        final int delta = -1;
        BinaryOperator<Integer> add = (x, y) -> x+y+delta;
        Integer apply = add.apply(1, 2);//結(jié)果是2
        System.out.println(apply);
    }

}

運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

在這個(gè)例子中, delta 是 Lambda 表達(dá)式中的外層局部變量,被聲明為 final,我們的 Lambda 表達(dá)式是對(duì)兩個(gè)輸入?yún)?shù) x,y 和外層局部變量 delta 進(jìn)行求和。

如果這個(gè)變量是一個(gè)既成事實(shí)上的 final 變量的話,就可以不使用 final 關(guān)鍵字。所謂個(gè)既成事實(shí)上的 final 變量是指只能給變量賦值一次,在我們的第一個(gè)例子中,delta 只在初始化的時(shí)候被賦值,所以它是一個(gè)既成事實(shí)的 final 變量。

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
import java.util.function.BinaryOperator;

public class LambdaTest2 {

    public static void main(String[] args) {
        int delta = -1;
        BinaryOperator<Integer> add = (x, y) -> x+y+delta;
        Integer apply = add.apply(1, 2);//結(jié)果是2
        System.out.println(apply);
    }

}
運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

相較于第一個(gè)例子,我們刪除了 final 關(guān)鍵字,程序沒(méi)有任何問(wèn)題。

1.2 在 Lambda 表達(dá)式當(dāng)中被引用的變量的值不可以被更改

在 Lambda 表達(dá)式中試圖修改局部變量是不允許的,那么我們?cè)诤竺鎸?duì) delta 賦值會(huì)怎么樣呢?

public static void main(String...s){
    int delta = -1;
    BinaryOperator<Integer> add = (x, y) -> x+y+ delta; //編譯報(bào)錯(cuò)
    add.apply(1,2);  
    delta = 2;
}

這個(gè)時(shí)候編譯器會(huì)報(bào)錯(cuò)說(shuō):

Variable used in lambda expression should be final or effectively final

1.3 在 Lambda 表達(dá)式當(dāng)中不允許聲明一個(gè)與局部變量同名的參數(shù)或者局部變量

public static void main(String...s){
    int delta = -1;
    BinaryOperator<Integer> add = (delta, y) -> delta + y + delta; //編譯報(bào)錯(cuò)
    add.apply(1,2);  
}

我們將表達(dá)式的第一個(gè)參數(shù)的名稱(chēng)由 x 改為 delta 時(shí),編譯器會(huì)報(bào)錯(cuò)說(shuō):

Variable 'delta' is already defined in the scope

2. 訪問(wèn)對(duì)象字段與靜態(tài)變量

Lambda 內(nèi)部對(duì)于實(shí)例的字段和靜態(tài)變量是即可讀又可寫(xiě)的。

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
import java.util.function.BinaryOperator;

public class Test {
    public static int staticNum;
    private int num;

    public void doTest() {
        BinaryOperator<Integer> add1 = (x, y) -> {
            num = 3;
            staticNum = 4;
            return x + y + num + Test.staticNum;
        };
        Integer apply = add1.apply(1, 2);
        System.out.println(apply);
    }

    public static void main(String[] args) {
        new Test().doTest();
    }

}
運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

這里我們?cè)?Test類(lèi)中,定義了一個(gè)靜態(tài)變量 staticNum 和 私有變量 num。并在 Lambda 表達(dá)式 add1 中對(duì)其作了修改,沒(méi)有任何問(wèn)題。

3. 關(guān)于引用值,而不是變量

通過(guò)前面兩節(jié)我們對(duì)于 Lambda 表達(dá)式的變量和作用域有了一個(gè)概念,總的來(lái)說(shuō)就是:

Tips: Lambda 表達(dá)式可以讀寫(xiě)實(shí)例變量,只能讀取局部變量。

有沒(méi)有想過(guò)這是為什么呢?

  • 實(shí)例變量和局部變量的實(shí)現(xiàn)不同:實(shí)例變量都存儲(chǔ)在堆中,而局部變量則保存在棧上。如果在線程中要直接訪問(wèn)一個(gè)非final局部變量,可能線程執(zhí)行時(shí)這個(gè)局部變量已經(jīng)被銷(xiāo)毀了。因此,Java 在訪問(wèn)自由局部變量時(shí),實(shí)際上是在訪問(wèn)它的副本,而不是訪問(wèn)原始變量。如果局部變量?jī)H僅賦值一次那就沒(méi)有什么區(qū)別了——因此就沒(méi)有這個(gè)限制(也就是既成事實(shí)的 final)。
  • 這個(gè)局部變量的訪問(wèn)限制也是 Java 為了促使你從命令式編程模式轉(zhuǎn)換到函數(shù)式編程模式,這樣會(huì)很容易使用 Java 做到并行處理(關(guān)于命令式編程模式和函數(shù)式編程模式我們將在后續(xù)內(nèi)容中做詳細(xì)的解釋?zhuān)?/li>

4. 小結(jié)

本節(jié)我們主要介紹了 Lambda 表達(dá)式的變量作用域,主要有這么 3 點(diǎn)需要記住:

  • 引用值,而不是變量;
  • 可以讀寫(xiě)實(shí)例變量;
  • 只能讀取局部變量。

最后我們對(duì)于 Lambda 表達(dá)式對(duì)于變量為什么會(huì)有這樣的訪問(wèn)限制做了相應(yīng)的分析。