Come noto, quando si effettua l'accumulo, "reduce" restituisce sempre un nuovo oggetto immutabile mentre "collect" apporta le modifiche su un oggetto mutabile.Java 8 collect vs reduce
Tuttavia, quando accidentalmente assegno un riferimento al metodo per ridurre e raccogliere il metodo, esso viene compilato senza errori. Perché?
Date un'occhiata al codice seguente:
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);
}
}
Penso che [15.13.2] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.13.2) sia più rilevante in questo caso - - "Un'espressione di riferimento del metodo è compatibile in un contesto di assegnazione [...] con un tipo di destinazione T [...] se [...]] Il risultato del tipo di funzione [di T] è vuoto " –
ok, penso che la spiegazione sia abbastanza chiara. Non sono sicuro del motivo per cui questo è accettato, poiché causerà errori nella maggior parte dei casi. – ning
La motivazione è corretta: proprio come è possibile invocare un metodo e scartare il tipo restituito, è possibile convertire un metodo risultante in un'interfaccia funzionale che restituisce un vuoto. Il commentatore precedente teme che questa flessibilità inviti bug, ma il l'alternativa era peggiore - non si poteva nemmeno convertire 'aList :: add' in un' Consumer', dato che 'add' restituisce qualcosa - e questo sarebbe davvero fastidioso, se non si potesse dire' x.for Ogni (lista: : add) '! O una soluzione stava per infastidire qualcuno, in questo modo è stato giudicato il minore dei mali e, in realtà, non era nemmeno una chiamata ravvicinata –