Java, Google Collections Library; problema con AbstractIterator?
Domanda
Sto utilizzando la libreria Google Collections AbstractIterator per implementare un generatore. Mi sono imbattuto in un problema mentre lo facevo; L'ho ridotto a un tipo più semplice e ho riprodotto il problema. Questa riduzione è ovviamente eccessiva per quello che fa, contando da 1 a numeri tramite Iterable.
Essenzialmente nel seguente codice, la versione non commentata funziona e quella commentata no (fornisce un elemento null ultimo, anziché terminare con l'ultimo numero).
Sto facendo qualcosa di sbagliato o è un problema con la libreria?
private Iterable<Integer> elementGenerator(final int numelements) {
return new Iterable<Integer>() {
@Override public Iterator<Integer> iterator() {
return new AbstractIterator<Integer>(){
int localcount=0;
@Override protected Integer computeNext() {
if (localcount++ == numelements) return endOfData();
return localcount;
// return (localcount++ == numelements) ? endOfData() : localcount;
}
};
}
};
}
Ho anche provato a armeggiare con la disposizione ?:
(ad esempio, prefissando il ritorno e confrontando invece con +1), senza alcun risultato. Ho cercato un po 'di documentazione in merito, ma non ho trovato nulla. Ovviamente, la sintassi ?:
è solo una comodità, non una necessità, ma comunque ...
Soluzione
Ottieni un NullPointerException
a causa dell'uso dell'operatore ternario, espressione condizionale, con diversi tipi numerici. Java ha regole complesse quando si mescolano valori numerici di diversi tipi nell'espressione ternaria: JLS Sezione 15.25
.
Dato che endOfData ()
è preceduto dalla restituzione di Integer
, mentre localcount
è un int
, Java unboxes il valore di endOfData ()
. Tuttavia, dato che endOfData ()
restituisce un valore null, l'operazione di unboxing si traduce in un'eccezione puntatore null.
Puoi continuare a utilizzare l'istruzione if oppure dichiarare localcount come Integer
.
Altri suggerimenti
Mi aspetto che il problema riguardi l'uso dell'operatore postincremento, insieme anche all'operatore ternario. Perché a parte questo, i due frammenti dovrebbero essere del tutto equivalenti - e difficilmente è colpa dell'astrattoIteratore se non sono poiché nessuno del suo codice viene chiamato a quel punto.