2015-09-15 32 views
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); 
    } 
} 

输出:的Java 8 LAMBDA翻译与incompatiable参数

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

这成功地运行在1.8.0_45.jdk。 Container#add如何被转换为ObjIntConsumer#accept?

回答

6

方法Container.add是需要调用实例的实例方法。由于形式为ClassName::methodName的方法引用未绑定到实例,因此Container::add的功能签名为(Container<T>,T)

由于您没有为Container指定类型参数,也没有指定目标类型,因此编译器会推断出Container<Object>。所以Container::add在这里具有推断的签名(Container<Object>,Object),这适用于方法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,例如SerializableNumber,也可以工作。


你可以阅读更多关于“What does ‘an Arbitrary Object of a Particular Type’ mean in java 8?”以实例方法无界引用。


作为一个侧面说明,流的collect方法不应该接受null参数和Stream实现没有。通过null与原始流一起工作是当前实现中的一个小故障,通过null的代码有可能在下一个版本中破解。作为Tagir Valeev pointed out,在Java 9的当前开发状态​​下,行为已经是changed

+4

顺便说一句,我很惊讶'IntStream'接受'null'作为'collect'的最后一个参数。标准的'Stream'实现没有。 – Holger

+3

JDK-9中的[已经修复](http://hg.openjdk.java.net/jdk9/dev/jdk/diff/013baa71b58b/src/share/classes/java/util/stream/IntPipeline.java)因此我不会这样写 –

+0

我的困惑不在于拳击,拆箱。我提供了一个参数“add(T t)”的方法,但是它被转换为2个参数accept(T t,int value)。我期望的是这样的: required:java.lang.Integer found:java.lang.Integer,int reason:实际和形式参数列表的长度不同 –