gpt4 book ai didi

java - 为什么方法引用可以使用非最终变量?

转载 作者:IT老高 更新时间:2023-10-28 21:00:37 26 4
gpt4 key购买 nike

我对内部类和 lambda 表达式有些困惑,我试图问一个 question关于这一点,但随后出现了另一个疑问,与评论前一个问题相比,发布另一个问题可能更好。

直截了当:我知道(thank you Jon)这样的东西不会编译

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 不是 [有效地] final 等等。

但是,怎么会允许呢?

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 吗?在第二种情况下,我不是面临“使用过时变量”的风险吗?

我的意思是,在后一种情况下,在执行 one = new One(); 之后 f 仍然有一个过期的 one(即引用旧对象)。这不是我们要避免的那种模棱两可吗?

最佳答案

方法引用不是 lambda 表达式,尽管它们可以以相同的方式使用。我认为这就是造成困惑的原因。下面是 Java 工作原理的简化,并不是它真正的工作原理,但已经足够接近了。

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

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

这相当于实现Runnable的匿名类:

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

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

另一方面,方法句柄:

Runnable f = one::bar;

更像是:

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

MethodHandle 为:

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 的对象被分配为创建的方法句柄的一部分,因此 one 本身不需要有效地为 this工作。

关于java - 为什么方法引用可以使用非最终变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33052917/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com