2012-11-22 3 views
35

Io non sapevo nemmeno che questo era fattibile, ma ho visto mentre sfogliando un codice in linea un metodo con una firma come questo:Qual è lo scopo della lista <Void>?

public List<Void> read(...) 

... Cosa? C'è mai una ragione per farlo? Cosa potrebbe contenere anche questo ? Per quanto ne sapevo, non è possibile istanziare un oggetto Void.

+0

in java o dove? – AlexWien

+1

Il posto dove hai visto il codice non l'ha spiegato? Non riesco a trovare alcuno scopo per ora. – Pablo

+1

http://docs.oracle.com/javase/6/docs/api/java/lang/Void.html –

risposta

23

E 'possibile che questa firma del metodo è stata creata come sottoprodotto di alcune classi generiche.

Ad esempio, SwingWorker ha due parametri tipo, uno per il risultato finale e uno per i risultati intermedi. Se non si desidera utilizzare alcun risultato intermedio, si passa Void come parametro del tipo, con la conseguente restituzione di alcuni metodi Void - vale a dire nulla.

Se ci fosse un metodo List<V> returnAllIntermediateResults() in SwingWorker con Void come parametro tipo V, avrebbe creato un metodo proprio come hai postato nella sua interrogazione.

Il codice sarebbe perfettamente valido. È possibile creare un'istanza per qualsiasi implementazione dell'interfaccia List (ad esempio ArrayList) con il parametro di tipo Void. Ma l'unico valore che può avere un tipo Void è null. Quindi l'elenco non può contenere altro se non null s, se l'implementazione consente gli elementi null.

+0

Vedo. Molto interessante! Questo è probabilmente quello che ho visto. Parlare di pazzi per prodotti. – asteri

+0

Buona risposta, ma è possibile creare tecnicamente un'istanza di Void tramite riflessione. Non ho idea del perché vorresti farlo comunque. – Dunes

+2

@Jeff Non mi piace molto il tipo Void. Di solito quando lo vedo, vuol dire che alcuni stereotipi di tipo incomprensibile avanzato stanno succedendo. L'unico uso "ragionevole" che ho visto era con SwingWorker. –

9

List<Void> è strano. Può avere solo elementi null, poiché non è possibile creare un oggetto di tipo Void. Non penso che ci sia un uso pratico per una cosa del genere.

Void è parte di java.lang. Non è una parola chiave speciale o altro. È uno "pseudo-tipo" (secondo i documenti) utilizzato come segnaposto per rappresentare l'oggetto Class corrispondente a void, come in Class<Void>. Da the docs for Class:

I tipi Java primitivi (boolean, byte, char, short, int, long, float, e double), e la parola chiave void sono rappresentati anche come Class oggetti.

esiste La classe Void principalmente per il bene del l'ultima parte di questo, in modo da poter scrivere:

Class<Void> voidType = void.class; // == Void.TYPE 

proprio come si può scrivere:

Class<Integer> intType = int.class; // == Integer.TYPE 
4

Sono d'accordo, è strano.

Posso vederne un uso se si desidera estendere una classe generica e restituire void da un metodo. Mi sono imbattuto in un caso che volevo usare int e ho dovuto usare Integer perché i generici java non amano i tipi primitivi.

public interface ObjectUserPool<E, T> { 
    public E useObject(T o); 
} 

public class NonReturningObjectUserPool extends ObjectUserPool<Void, Integer> { 
    public Void useObject(Integer i); 
} 

Credo che questo è ciò che l'API Java sta dicendo, anche se ad essere onesti non posso davvero trovare un impiego per NonReturningObjectUserPool.

+1

È possibile restituire "null" per qualsiasi tipo di riferimento; non richiede nulla di speciale come 'Void'. –

+1

@TedHopp buon punto, risposta modificata. Penso che sia ancora valido voler rendere nulla il self documenting; piuttosto che pretendere di restituire Integer e poi internamente restituendo sempre null, e rivendicando in javadoc che tu restituisca sempre null o qualcosa del genere. –

10

Un caso in cui può essere utile è se si desidera restituire una raccolta di valori restituiti da una funzione. Dì

static List<T> forEach(Func<A,T> func, List<A> items) { 
    List<T> ret = new List<T>(); 
    for(int i = 0; i< items.length; i++) { 
    ret.add(func.call(items[i]); 
    } 
    return ret; 
} 

public static void main() { 
    ... 
    List<Void> boringResult = 
    forEach(
    new Func<Void, Integer> {@override Void call(Integer i) {...}}); 
} 

Non è utile ma potresti vedere un caso in cui è stato richiesto.

+0

Huh. Parliamo di un caso marginale. Grazie per la tua risposta! Molto interessante. – asteri

+0

Aggiungere 'java.concurrent.Future' e' Callable' all'elenco. C'è un tipo di ritorno 'Void' non è raro. –

+0

L'unico valore restituito da 'Void call (Integer i) {...}' è 'null', poiché (in base a [i documenti] (http://docs.oracle.com/javase/6/docs/ api/java/lang/Void.html)): _ "La classe Void è una ** classe di segnaposto ** non applicabile ** (enfasi aggiunta). Non sono sicuro di quanto sia utile costruire un elenco che possa contenere solo riferimenti 'null'. –