具有不兼容参数的Java 8 Lambda转换

时间:2015-09-15 10:45:50

标签: lambda java-8 functional-interface

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?

1 个答案:

答案 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的类型参数,例如Numbercollect也可以使用。

您可以在“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