为什么Java 8中的lambda表达式要求在其中使用的变量使用"final"修饰符,但在使用方法引用时却不需要?

Mat*_*ari 9 java lambda java-8

考虑以下课程:

class Foo<T> {

    void handle(T t) {
        System.out.println("handling " + t);
    }

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);

        Foo<Integer> f = new Foo<>();

        list.forEach(f::handle);             // compiles fine
        //list.forEach(obj -> f.handle(obj));// compilation error

        f = new Foo<>(); // reassign f

    }
}
Run Code Online (Sandbox Code Playgroud)

为什么我会收到编译错误obj -> f.handle(obj),但不是f::handle

Gio*_*tta 14

这是两个不同的结构,它们做了两件不同的事情.在第一种情况下,您将获得特定对象的方法引用:这只需要执行一次,之后JVM对对象有自己的引用(如此有效地最终)f并且可以调用该handle方法.在第二种情况下,在每次调用时,JVM必须解析f引用,因此它f必须抱怨final.你可以很容易地编写代码,设置fnull同时forEach运行,从而导致NPE.