lambda表达式和全局变量

时间:2015-06-09 09:52:29

标签: java lambda

我刚开始在Java 8中使用lambda表达式。我对effectively final感到困惑。

初始化一次的局部变量是effectively final但是全局变量怎么样,我可以改变全局变量的值并在lambda表达式中使用它。那么局部变量背后的原因应该是effectively final。我找不到任何关于此的文章或javadoc。

import java.util.ArrayList;
import java.util.List;

public class Main {

    private String lastname = "Thakor";

    public static void main(String[] args) {
        Main objMain = new Main();
        objMain.test();
    }

    public void test(){
        List<String> listStrings = new ArrayList<String>();
        listStrings.add("Vicky");
        listStrings.add("Thakor");

        String middlename = "V";
        //Local variable middlename defined in an enclosing scope must be final or effectively final
        /* middlename = "T";*/ 

        /**
         * In case of global variable, why lambda expression not throwing error...
         * Local variable middlename defined in an enclosing scope must be final or effectively final
         */
        lastname = "T"; 

        listStrings.stream()
                        .forEach(firstname ->{
                            System.out.println("Firstname: " + firstname);
                            System.out.println("Middle: " + middlename);
                            System.out.println("Lastname: " + lastname);
                            System.out.println("--------------------------------------");
                        });
    }
}

输出

Firstname: Vicky
Middle: V
Lastname: T
--------------------------------------
Firstname: Thakor
Middle: V
Lastname: T
--------------------------------------

1 个答案:

答案 0 :(得分:6)

当您在lambda中引用“全局”变量时,您实际上正在捕获对this的引用,这实际上是最终的。

考虑以下代码段(未经测试):

class Main {

    class Box {
        int value;
    }

    void foo() {
        Box box = new Box();
        Runnable r = () -> box.value++;
    }
}

即使您正在更改box.value,也可以通过box引用来实现,这实际上是最终的。同样,您的代码等同于

System.out.println("Lastname: " + this.lastname);

意味着您通过lastname引用访问this,这实际上是最终的。