Как известно, при выполнении накоплений «сокращение» всегда возвращает новый неизменяемый объект, а «collect» будет вносить изменения в изменяемый объект.Java 8 collect vs reduce
Однако, когда я случайно присваиваю одну ссылку методу методу уменьшения и сбора, он компилируется без каких-либо ошибок. Зачем?
Взгляните на следующий код:
public class Test {
@Test
public void testReduce() {
BiFunction<MutableContainer,Long,MutableContainer> func =
MutableContainer::reduce;
// Why this can compile?
BiConsumer<MutableContainer,Long> consume =
MutableContainer::reduce;
// correct way:
//BiConsumer<MutableContainer,Long> consume =
// MutableContainer::collect;
long param=10;
MutableContainer container = new MutableContainer(0);
consume.accept(container, param);
// here prints "0",incorrect result,
// because here we expect a mutable change instead of returning a immutable value
System.out.println(container.getSum());
MutableContainer newContainer = func.apply(container, param);
System.out.println(newContainer.getSum());
}
}
class MutableContainer {
public MutableContainer(long sum) {
this.sum = sum;
}
public long getSum() {
return sum;
}
public void setSum(long sum) {
this.sum = sum;
}
private long sum;
public MutableContainer reduce(long param) {
return new MutableContainer(param);
}
public void collect(long param){
this.setSum(param);
}
}
Я думаю, что [15.13.2] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.13.2) более уместен в этом случае - - «Ссылочное выражение метода совместимо в контексте назначения [...] с целевым типом T [...], если [...] Результат типа функции [из T] недействителен « –
ОК, я думаю, что объяснение достаточно ясное. Не уверен, почему это принято, поскольку в большинстве случаев это вызовет ошибку. Сильная проверка типов должна предотвратить такую ошибку – ning
Вы правы в мотивации. Так же, как вы можете вызвать метод и отказаться от типа возврата, вы можете преобразовать метод, основанный на результатах, в функциональный интерфейс, возвращающий пустоту. Предыдущий комментатор опасается, что эта гибкость вызывает ошибки, но альтернатива была хуже - вы даже не могли преобразовать 'aList :: add' в' Consumer', так как 'add' возвращает что-то - и это было бы очень неприятно, если вы не могли бы сказать' x.forEach (list: : add) '! Любое решение должно было раздражать кого-то. Этот путь был признан меньшим количеством зла. И действительно, это был даже не звонок. –