为什么方法引用不是单例?

Dim*_*e98 22 java lambda conceptual java-8

在Java中,以下代码在两个查询上都返回false.为什么?方法引用是单例是不是更简单?它肯定会使听众的连接和分离变得更加简单.因为您需要为需要进行等效性检查的任何方法引用保持常量,所以不能在每个必要位置使用方法引用运算符.

public class Main {

    public Main() {
        // TODO Auto-generated constructor stub
    }

    public void doStuff() {

    }

    public static void main(String[] args) {
        Main main = new Main();
        Runnable thing1 = main::doStuff;
        Runnable thing2 = main::doStuff;
        System.out.println(thing1 == thing2); // false
        System.out.println(thing1.equals(thing2)); // false
    }

}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 16

对于实例方法,我不认为它将使意义对它们进行缓存.你必须为每个实例缓存一个方法...这或者意味着与该方法相关联的类中的额外字段 - 每个公共方法一个,大概是因为这些方法可以从类外部引用 - 或者缓存在方法引用的用户,在这种情况下,您需要某种每实例缓存.

我认为对静态方法的方法引用进行缓存更有意义,因为它们将永远是相同的.但是,要缓存实际内容Runnable,您需要为其定位的每种类型的缓存.例如:

public interface NotRunnable {
    void foo();
}

Runnable thing1 = Main::doStuff; // After making doStuff static
NotRunnable thing2 = Main::doStuff;
Run Code Online (Sandbox Code Playgroud)

在这里应该thing1thing2平等吗?如果是这样,编译器将如何知道要创建的类型?它可以在这里创建两个实例并单独缓存它们 - 并始终在使用点缓存而不是方法声明点.(您的示例具有相同的类,声明方法并引用它,这是一个非常特殊的情况.您应该考虑更一般的情况,它们是不同的>)

JLS 允许缓存方法引用.从第15.13.3节:

接下来,分配并初始化具有以下属性的类的新实例,或者引用具有以下属性的类的现有实例.

...但即使是静态方法,它似乎javac也没有进行任何缓存.