2
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?

4

1 回答 1

6

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

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

第二个参数可以接受type 的值int,因为在将其装箱后Integer,它可以分配给Object

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

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

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


您可以在“Java 8 中的‘特定类型的任意对象’是什么意思?”中阅读更多关于实例方法的无限引用的信息</a>。


作为旁注,collect流的方法不应该接受null参数并且Stream实现不接受。与原始流一起工作的传递是null当前实现中的一个小故障,传递null的代码可能会在下一个版本中中断。正如Tagir Valeev 指出的那样,在Java 9 的当前开发状态​​中,行为已经发生了变化。

于 2015-09-15T10:57:01.077 回答