Java 8 参数不兼容的 Lambda 翻译

Java 8 Lambda translation with incompatiable arguments

import org.junit.Test;

import java.util.stream.IntStream;

public class GomanTest {

    @Test
    public void someTest() {
        IntStream.of(2, 3, 1).collect(Container::new, Container::add, null);
    }
}


class Container<T> {

    void add(T t) {
        System.out.println("this is container " + t);
    }
}

输出:

this is container 2
this is container 3
this is container 1

这在 1.8 上运行成功。0_45.jdk。 Container#add 如何转换为 ObjIntConsumer#accept?

方法Container.add是一个需要调用实例的实例方法。由于 ClassName::methodName 形式的方法引用未绑定到实例,因此 Container::add 具有 (Container<T>,T).

的功能签名

由于您没有为 Container 指定类型参数,也没有指定目标类型,编译器将推断 Container<Object>。所以Container::add这里有推断的签名(Container<Object>,Object),适用于ObjIntConsumer<Container<Object>>accept方法,它有签名(Container<Object>,int).

第二个参数可以接受类型int的值,因为在将它装箱到Integer之后,它可以分配给Object.

如果将结果分配给变量,则同样有效,从而提供 Container<Object>Container<Integer> 的目标类型,如

Container<Integer> collected
   = IntStream.of(2, 3, 1).collect(Container::new, Container::add, null);

任何可以使用 Integer 的类型参数,例如SerializableNumber 也可以。


您可以在 “What does ‘an Arbitrary Object of a Particular Type’ mean in java 8?”.

中阅读更多关于对实例方法的无限引用的信息

附带说明一下,流的 collect 方法不应该接受 null 参数,而 Stream 实现也不会。传递 null 与原始流一起工作是当前实现中的一个小故障,传递 null 的代码可能会在下一个版本中中断。作为 , the behavior has already changed 在 Java 9.

当前的发展状态