功能接口和方法引用的行为

Behavior of Functional Interface and Method Reference

当属于变量的方法引用被销毁时会发生什么?

public class Hey{
    public double bar;

    public Hey(){
        bar = 2.0d;
    }

    public double square(double num){
        return Math.pow(num , bar);
    }
}

Function<Double, Double> square;
whatsGonnaHappen: {
    Hey hey = new Hey();
    square = hey::square;
}//is hey still kept around because its method is being referenced?

double ans = square.apply(23d);

作用域是一个编译时概念,它控制源代码中名称的使用位置。 From the JLS

The scope of a declaration is the region of the program within which the entity declared by the declaration can be referred to using a simple name, provided it is visible (§6.4.1).

名称 hey 仅限于 whatsGonnaHappen 标记语句的主体这一事实与 hey 在运行时引用的实例是否是垃圾收集的候选人(我想这就是你担心的)。

关于变量捕获,是的,方法引用hey::square是对特定对象(hey引用的对象)的实例方法的引用,因此将捕获当评估方法引用表达式以生成实例并在调用 apply 时使用它时变量 hey

您的方法参考基本上等同于这样做:

Hey hey = new Hey();
Function<Double, Double> square = new DoubleDoubleFunction(hey);

其中 class DoubleDoubleFunction 是这样定义的

class DoubleDoubleFunction implements Function<Double, Double> {
    private final Hey hey;

    public DoubleDoubleFunction(Hey hey) {
        this.hey = hey;
    }

    @Override
    public Double apply(Double num) {
        return hey.square(num);
    }
}

换句话说,square 持有对 Hey 的引用。

我不知道 eclipse,但使用 IntelliJ,您可以轻松地将方法引用和 lambda 转换为匿名/静态嵌套/内部 classes 以查看发生了什么。我发现这是一件很有启发性的事情。