2015-09-15 4 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. Как добавляется контейнер # add, переводимый в ObjIntConsumer # accept?

ответ

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, также будет работать.


Вы можете прочитать больше о неограниченных ссылок на методы экземпляра в “What does ‘an Arbitrary Object of a Particular Type’ mean in java 8?”.


В качестве примечания, то collect методов потоков не должны принимать null аргументов и Stream реализации не делает. Прохождение null работает с примитивными потоками - это сбой в текущей реализации, и код, который проходит null, скорее всего, сломается в следующей версии. Как Tagir Valeev pointed out, поведение уже changed в текущем состоянии развития Java 9.

+4

Кстати, я удивлен, что 'IntStream' принимает' null' в качестве последнего аргумента 'collect'. Стандартная реализация «Stream» не работает. – Holger

+3

Это [уже исправлено] (http://hg.openjdk.java.net/jdk9/dev/jdk/diff/013baa71b58b/src/share/classes/java/util/stream/IntPipeline.java) в JDK-9, таким образом, я бы не писал это так –

+0

Мое замешательство не связано с боксом, распаковкой. Я предоставляю метод с одним аргументом «add (T t)», но он преобразуется в 2 аргумента accept (T t, int value). Я ожидаю что-то вроде этого: Требуется: java.lang.Integer найдено: java.lang.Integer, int Причина: фактические и формальные списки аргументов различаются по длине –

Смежные вопросы