为什么方法引用使用非最终变量? [英] Why can method reference use non-final variables?

查看:164
本文介绍了为什么方法引用使用非最终变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对内部类和lambda表达有些困惑,我试图问一个问题,但随后出现了另一个疑问,并且可能更好地发布另一个问题,而不是对前一个问题进行评论。

I had some confusion about inner classes and lambda expression, and I tried to ask a question about that, but then another doubt arose, and It's probable better posting another question than commenting the previous one.

直截了当:我知道(谢谢Jon& / a>)这样的东西不会编译

Straight to the point: I know (thank you Jon) that something like this won't compile

public class Main {
    public static void main(String[] args) {
        One one = new One();

        F f = new F(){      //1
            public void foo(){one.bar();}   //compilation error
        };

        one = new One();
    }
}

class One { void bar() {} }
interface F { void foo(); }

因为Java管理闭包,因为 one

due to how Java manages closures, because one is not [effectively] final and so on.

但是,这是为什么呢?

public class Main {
    public static void main(String[] args) {
        One one = new One();

        F f = one::bar; //2

        one = new One();
    }
}

class One { void bar() {} }
interface F { void foo(); }

不是 // 2 // 1 ?在第二种情况下,我不是面临使用过时的变量的风险吗?

Is not //2 equivalent to //1? Am I not, in the second case, facing the risks of "working with an out-of-date variable"?

我的意思是,在后一种情况下, one = new One(); c> f 仍然有过期的一个副本(即引用旧对象)。

I mean, in the latter case, after one = new One(); is executed f still have an out of date copy of one (i.e. references the old object). Isn't this the kind of ambiguity we're trying to avoid?

推荐答案

方法引用不是一个lambda表达式,虽然它们可以以相同的方式使用。我认为这是造成混乱的原因。

A method reference is not a lambda expression, although they can be used in the same way. I think that is what is causing the confusion. Below is a simplification of how Java works, it is not how it really works, but it is close enough.

假设我们有一个lambda表达式:

Say we have a lambda expression:

Runnable f = () -> one.bar();

这相当于一个匿名类,实现 Runnable

This is the equivalent of an anonymous class that implements Runnable:

Runnable f = new Runnable() {
    public void run() {
       one.bar();
    }
}

这里的规则适用于匿名类或方法本地类)。这意味着 one 需要有效的最终工作。

Here the same rules apply as for an anonymous class (or method local class). This means that one needs to effectively final for it to work.

另一方面,方法句柄: / p>

On the other hand the method handle:

Runnable f = one::bar;

更像:

Runnable f = new MethodHandle(one, one.getClass().getMethod("bar"));

使用 MethodHandle

With MethodHandle being:

public class MethodHandle implements Runnable {
    private final Object object;
    private final Method method;

    public MethodHandle(Object object, java.lang.reflect.Method method) {
        this.object = Object;
        this.method = method;
    }

    @Override
    public void run() {
        method.invoke(object);
    }
}

在这种情况下,分配给 one 是作为创建的方法句柄的一部分分配的,因此一个本身不需要有效地最终使这个工作。

In this case, the object assigned to one is assigned as part of the method handle created, so one itself doesn't need to be effectively final for this to work.

这篇关于为什么方法引用使用非最终变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆