Il existe un Java Void
- majuscule V-- type de référence . La seule situation dans laquelle je l'ai jamais vue est celle de paramétrer Callable
s
final Callable<Void> callable = new Callable<Void>() {
public Void call() {
foobar();
return null;
}
};
Existe-t-il d'autres utilisations du type de référence Java Void
?? Peut-on lui attribuer autre chose que null
?? Si oui, avez-vous des exemples?
Void
est devenu la convention d'un argument générique qui ne vous intéresse pas. Il n'y a aucune raison pour que vous utilisiez un autre type non instanciable, tel que System
.
Il est également souvent utilisé par exemple dans Map
valeurs (bien que Collections.newSetFromMap
utilise Boolean
car les cartes ne doivent pas accepter les valeurs null
) et Java.security.PrivilegedAction
.
J'ai écrit un entrée de blog sur Void
il y a quelques années.
Vous pouvez créer une instance de Void en utilisant des réflexions, mais elles ne servent à rien. Void est un moyen d'indiquer qu'une méthode générique ne renvoie rien.
Constructor<Void> constructor = Void.class.getDeclaredConstructor();
constructor.setAccessible(true);
Void v = constructor.newInstance();
System.out.println("I have a " + v);
imprime quelque chose comme
I have a Java.lang.Void@75636731
Future<Void>
fonctionne comme un charme. :)
Étant donné qu'il y a pas de constructeurs publics , je dirais qu'il ne peut être attribué rien d'autre que null
. Je ne l'ai utilisé que comme paramètre fictif pour "Je n'ai pas besoin d'utiliser ce paramètre générique", comme le montre votre exemple.
Il pourrait également être utilisé en réflexion, à partir de ce que son Javadoc dit:
La classe Void est une classe fictive non instanciable destinée à contenir une référence à l'objet Class représentant le mot clé Java void.).
Toutes les classes de wrapper primitives (Integer
, Byte
, Boolean
, Double
, etc.) contiennent une référence à la classe primitive correspondante dans un statique TYPE
champ, par exemple:
Integer.TYPE == int.class
Byte.TYPE == byte.class
Boolean.TYPE == boolean.class
Double.TYPE == double.class
Void
a été créé à l'origine pour créer une référence au type void
:
Void.TYPE == void.class
Cependant, vous ne gagnez rien en utilisant Void.TYPE
. Quand vous utilisez void.class
_ il est beaucoup plus clair que vous faites quelque chose avec le type void
.
En passant, la dernière fois que j'ai essayé, BeanShell n'a pas reconnu void.class
, vous devez donc utiliser Void.TYPE
Là.
Lorsque vous utilisez le motif visiteur , il peut être plus simple d'utiliser Void au lieu de Object lorsque vous voulez être sûr que la valeur de retour sera null
Exemple
public interface LeavesVisitor<OUT>
{
OUT visit(Leaf1 leaf);
OUT visit(Leaf2 leaf);
}
Lorsque vous implémentez votre visiteur, vous pouvez explicitement définir OUT comme étant Void afin que vous sachiez que votre visiteur retournera toujours la valeur null au lieu d'utiliser 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;
}
}
Avant les génériques, il avait été créé pour l'API de réflexion afin de contenir TYPE renvoyé par Method.getReturnType () pour une méthode void, correspondant aux autres classes de type primitives.
EDIT: A partir du JavaDoc de Void: "La classe Void est une classe fictive non instable) destinée à contenir une référence à l'objet Class représentant le Java"). Avant Generics, je n’étais conscient que de la réflexion.
Comme vous ne pouvez pas instancier Void, vous pouvez utiliser objet Null commun Apache , donc
Null aNullObject = ObjectUtils.Null;
Null noObjectHere = null;
dans la première ligne, vous avez un objet, donc aNullObject != null
est valide, alors que dans la deuxième ligne il n’ya pas de référence, donc noObjectHere == null
détient
Pour répondre à la question initiale de l'affiche, son utilisation est de différencier "le rien" et le "rien", qui sont des choses complètement différentes.
PS: Dites non au motif d'objet nul
Void est créé pour envelopper son type de vide primitif. Chaque type de primitive a son type de référence correspondant. Void est utilisé pour instancier une classe générique ou pour utiliser une méthode générique, un argument générique auquel vous n'êtes pas intéressé. Voici un exemple ...
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());
}
});
}
ici, comme vous pouvez le constater, je ne veux rien du serveur auquel je demande de créer un nouvel enregistrement, mais public interface AsyncCallback<T> { .... }
est une interface générique, je fournis donc Void car les génériques n’acceptent pas les types primitifs
Il est également couramment utilisé sur les rappels d'achèvement Async-IO lorsque vous n'avez pas besoin d'un objet Attachment
. Dans ce cas, vous spécifiez null pour l'opération IO et implémentez CompletionHandler<Integer,Void>
.
C'est peut-être un cas rare mais une fois, j'ai utilisé Void
dans les classes d'aspect.
C'était un aspect qui court après des méthodes qui a un @Log
annotation, et enregistre la méthode retournée et quelques informations si le type de retour de la méthode n’est pas annulé.
@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
}
}