Usi per il tipo di riferimento Java Void?
Domanda
Esiste un Java Void
- V maiuscola-- tipo di riferimento . L'unica situazione che io abbia mai visto usato è parametrizzare Callable
s
final Callable<Void> callable = new Callable<Void>() {
public Void call() {
foobar();
return null;
}
};
Ci sono altri usi per il tipo di riferimento Java null
? Può mai essere assegnato qualcosa di diverso da <=>? Se sì, hai degli esempi?
Soluzione
Void
è diventato una convenzione per un argomento generico a cui non sei interessato. Non vi è alcun motivo per cui dovresti usare qualsiasi altro tipo non istantaneo, come System
.
Viene spesso utilizzato ad esempio nei Map
valori (sebbene Collections.newSetFromMap
usi Boolean
poiché le mappe non devono accettare null
valori) e java.security.PrivilegedAction
.
Ho scritto una voce nel blog il <=> qualche anno fa.
Altri suggerimenti
Puoi creare un'istanza di Void usando le riflessioni, ma non sono utili a nulla. Void è un modo per indicare che un metodo generico non restituisce nulla.
Constructor<Void> constructor = Void.class.getDeclaredConstructor();
constructor.setAccessible(true);
Void v = constructor.newInstance();
System.out.println("I have a " + v);
stampa qualcosa di simile
I have a java.lang.Void@75636731
Future<Void>
funziona come il fascino. :)
Dato che non ci sono nessun costruttore pubblico , Direi che non può essere assegnato altro che null
. L'ho usato solo come segnaposto per & Quot; Non ho bisogno di usare questo parametro generico, & Quot; come mostra il tuo esempio.
Potrebbe anche essere usato in riflessione, da ciò che è Javadoc dice:
La classe Void è una classe segnaposto non attendibile per contenere un riferimento all'oggetto Class che rappresenta il vuoto della parola chiave Java.
Tutte le classi wrapper primitive (Integer
, Byte
, Boolean
, Double
, ecc.) contengono un riferimento alla classe primitiva corrispondente in un campo TYPE
statico, ad esempio:
Integer.TYPE == int.class
Byte.TYPE == byte.class
Boolean.TYPE == boolean.class
Double.TYPE == double.class
Void
è stato inizialmente creato come da qualche parte per mettere un riferimento al void
tipo:
Void.TYPE == void.class
Tuttavia, non si guadagna davvero nulla usando Void.TYPE
. Quando usi void.class
è molto più chiaro che stai facendo qualcosa con il tipo <=>.
A parte, l'ultima volta che l'ho provato, BeanShell non ha riconosciuto <=>, quindi devi usare <=> lì.
Quando usi il modello di visitatore può essere più pulito usare Void invece di Object quando vuoi essere sicuro che il valore restituito sarà null
Esempio
public interface LeavesVisitor<OUT>
{
OUT visit(Leaf1 leaf);
OUT visit(Leaf2 leaf);
}
Quando implementerai il tuo visitatore, puoi impostare esplicitamente OUT su Void in modo che tu sappia che il tuo visitatore restituirà sempre null, invece di usare Object
public class MyVoidVisitor implements LeavesVisitor<Void>
{
Void visit(Leaf1 leaf){
//...do what you want on your leaf
return null;
}
Void visit(Leaf2 leaf){
//...do what you want on your leaf
return null;
}
}
Prima dei generici, è stato creato per l'API di riflessione, per contenere TYPE restituito da Method.getReturnType () per un metodo void, corrispondente alle altre classi di tipi primitivi.
EDIT: da JavaDoc of Void: " La classe Void è una classe segnaposto non attendibile per contenere un riferimento all'oggetto Class che rappresenta la parola chiave Java void " ;. Prima di Generics, sono a conoscenza di nessun uso diverso dalla riflessione.
Poiché non è possibile creare un'istanza di Void, è possibile utilizzare Apache commons Null object , quindi
Null aNullObject = ObjectUtils.Null;
Null noObjectHere = null;
nella prima riga, hai un oggetto, quindi aNullObject != null
trattiene, mentre nella seconda riga non ci sono riferimenti, quindi noObjectHere == null
trattiene
Per rispondere alla domanda originale del poster, l'uso per questo è di distinguere tra " il nulla " e " niente " ;, che sono cose completamente diverse.
PS: dì no al modello di oggetto Null
Il vuoto è creato per avvolgere il suo tipo di vuoto primitivo. Ogni tipo primitivo ha il suo tipo di riferimento corrispondente. Void viene utilizzato per creare un'istanza di una classe generica o l'uso di un metodo generico, Argomenti generici che non ti interessano. Ecco un esempio ...
public void onNewRegistration() {
newRegistrationService.createNewUser(view.getUsername(), view.getPassword(),
view.getInitialAmount(), view.getCurrency(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
}
@Override
public void onSuccess(Void result) {
eventBus.fireEvent(new NewRegistrationSuccessEvent());
}
});
}
qui, come puoi vedere, non voglio nulla dal server che sto chiedendo di creare una nuova registrazione, ma public interface AsyncCallback<T> { .... }
è un'interfaccia generica, quindi fornisco Void poiché i generici non accettano tipi primitivi
Viene anche comunemente utilizzato sui callback di completamento Async-IO quando non si ha la necessità di un oggetto Attachment
. In tal caso si specifica null per l'operazione IO e si implementa CompletionHandler<Integer,Void>
.
Può essere raro, ma una volta ho usato Void
nelle classi di aspetto.
Questo era un aspetto che viene eseguito dopo i metodi con @Log
annotazione e registra il metodo restituito e alcune informazioni se il tipo restituito dal metodo non è nullo.
@AfterReturning(value = "@annotation(log)",
returning = "returnValue",
argNames = "joinPoint, log, returnValue"
)
public void afterReturning(final JoinPoint joinPoint, final Log log,
final Object returnValue) {
Class<?> returnType = ((MethodSignature) joinPoint.getSignature())
.getReturnType();
if (Void.class.isAssignableFrom (returnType)) ) {
//Do some log
}
}