普通实例化和包含方法引用的实例化的区别

Difference between normal instantiation and instantiation including method reference

为什么第一种情况下 SomeClass 只实例化一次,而第二种情况下实例化 n 次,其中 n 是流中元素的数量?

List<SomeClass> list = stream.map(new SomeClass()::method)
                            .collect(Collectors.toList());

List<SomeClass> list = stream.map(a -> {return new SomeClass().method(a);})
                            .collect(Collectors.toList());

本例中的方法“method”return对象本身(=returnthis)。

所以在第一种情况下,列表只包含一个对象,但是有 n 次。在第二种情况下,列表包含 n 个不同的对象。

重现问题: 主要:

Arrays.asList(true, false, true, false).stream().map(new SomeClass()::method)
                                                .collect(Collectors.toList());

System.out.println("----------------------");
        
Arrays.asList(true, false, true, false).stream().map(a -> {return new SomeClass().method(a);})
                .collect(Collectors.toList());

和SomeClass.java:

public class SomeClass {
    
    public SomeClass() {
        System.out.println(this);
    }
    
    public SomeClass method(Boolean b) {
        return this;
    }
}

因为在第一个片段中您只调用了一次 new SomeClass(),因为:

List<SomeClass> list = stream.map(new SomeClass()::method)
                             .collect(Collectors.toList());

实际上等于:

SomeClass s = new SomeClass();
List<SomeClass> list = stream.map(a -> s.method(a))
                             .collect(Collectors.toList());

您在实例 s 上调用方法 method(),在第一个代码片段中,该实例并未保存到变量中,而是直接使用

方法引用只有四种(参见this page中的“方法引用的种类”):

  • 引用静态方法
  • 引用特定对象的实例方法
  • 引用特定类型的任意对象的实例方法
  • 对构造函数的引用

不存在一种“每次都创建一个新对象”的方法引用,不管那是什么意思。 new SomeClass()::methodName属于第二种。它指的是一个特定对象的方法methodName。该对象是新创建的 SomeClass 对象。当调用该方法时,它不再创建任何 SomeClass 对象,因为它是对 那个特定 SomeClass 对象的 someMethod 的引用你是新创建的。

另一方面,lambda 表达式在每次调用时都会创建一个新的 SomeClass,因为 new SomeClass(){ ... }.