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?
答案 0 :(得分: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)
签名为int
。
第二个参数可以接受类型为Integer
的值,因为在将其装箱到Object
后,它可以分配给Container<Object>
。
如果您将结果分配给变量,从而提供Container<Integer>
或Container<Integer> collected
= IntStream.of(2, 3, 1).collect(Container::new, Container::add, null);
的目标类型
Integer
任何可以使用Serializable
的类型参数,例如Number
或collect
也可以使用。
您可以在“What does ‘an Arbitrary Object of a Particular Type’ mean in java 8?”中阅读有关实例方法的无限引用的更多信息。
作为旁注,流的null
方法不应该接受Stream
个参数而null
实现不接受。传递null
与原始流一起使用是当前实现中的一个小故障,通过<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&libraries=places&language=en"></script>
的代码很可能在下一个版本中中断。作为Tagir Valeev pointed out,Java 9当前开发状态中的行为已经changed。