1. 程式人生 > >lambda表示式:變數作用域

lambda表示式:變數作用域

如下程式碼中的變數count和text,沒有在lambda表示式中被定義,而是repeatMessage方法的引數變數

    public void repeatMessage(String text, int count){
        Runnable r = () -> {
            for (int i=0; i<count; i++){
                System.out.println(text);
                Thread.yield();
            }
        };
        new Thread(r).start();
    }

一個lambda表示式包括三部分:

1.一段程式碼。

2.引數。

3.只有變數的值。(“自由”指的是那些不是引數並且沒有在程式碼中定義的變數)

在lambda表示式中,被引用的變數的值不可以被更改,如下程式碼:

    public void repeatMessage(String text, int count){
        Runnable r = () -> {
            while (count > 0){
                count --; //錯誤,不能更改
                System.out.println(text);
                Thread.yield();
            };
        };
        new Thread(r).start();
    }
原因:更改lambda表示式中的變數不是執行緒安全的,自增、自減操作不是原子性的。

內部類也會捕獲閉合作用域中的值。在Java8前,內部類只允許訪問final的區域性變數。為了適應lambda表示式,這條規則現在放寬了。一個內部類可以訪問任何有效的final區域性變數,即任何值不會發生變化的變數。

在lambda表示式中不允許宣告一個與區域性變數同名的引數或者區域性變數,如下程式碼:

Path first = Paths.get("/usr/bin");
        Comparator<String> comparator =
                (first, second) -> Integer.compare(first.length(), second.length());
        //錯誤:變數first已經被定義了

lambda表示式中的this關鍵字的意義,如下程式碼:

class Application {
    public void doWork(){
        Runnable runner = () -> {
            System.out.println(this.toString());
        };
    }
}
this.toString()會呼叫Application物件的toString方法,而不是Runnable例項的toString方法