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

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

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

在開始之前我們需要明確一句話:

引用值,而不是變量!

引用值,而不是變量!

引用值,而不是變量!

重要的事情說三遍!??!

1. 訪問局部變量

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

訪問局部變量要注意如下 3 點:

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

現(xiàn)在我們來仔細(xì)說明下這三點。

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

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

首先我們來看一個例子:

實例演示
預(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);
    }

}

運行案例 點擊 "運行案例" 可查看在線運行效果

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

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

實例演示
預(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);
    }

}
運行案例 點擊 "運行案例" 可查看在線運行效果

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

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

在 Lambda 表達(dá)式中試圖修改局部變量是不允許的,那么我們在后面對 delta 賦值會怎么樣呢?

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

這個時候編譯器會報錯說:

Variable used in lambda expression should be final or effectively final

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

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

我們將表達(dá)式的第一個參數(shù)的名稱由 x 改為 delta 時,編譯器會報錯說:

Variable 'delta' is already defined in the scope

2. 訪問對象字段與靜態(tài)變量

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

實例演示
預(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();
    }

}
運行案例 點擊 "運行案例" 可查看在線運行效果

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

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

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

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

有沒有想過這是為什么呢?

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

4. 小結(jié)

本節(jié)我們主要介紹了 Lambda 表達(dá)式的變量作用域,主要有這么 3 點需要記?。?/p>

  • 引用值,而不是變量;
  • 可以讀寫實例變量;
  • 只能讀取局部變量。

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