J'ai une classe qui définit deux méthodes surchargées
public void handle(Void e)
protected void handle()
Évidemment, ils sont différents, en particulier handle(Void e)
is public
.
Quelle est la différence entre ces deux-là?
Comment appeler la première méthode? J'utilise handle(null)
- est-ce correct?
La première fonction est une fonction d'un seul argument, qui doit être fourni et ne peut valablement prendre que la valeur null
. Toute valeur autre que null ne sera pas compilée. La deuxième fonction ne prend aucun argument et la transmission de null
à celle-ci ne sera pas compilée.
Void
est une classe spéciale généralement utilisée uniquement pour la réflexion - son utilisation principale est de représenter le type de retour d'une méthode void. Depuis le javadoc pour Void
:
La classe Void est une classe d'espace réservé non instable pour contenir une référence à l'objet Class représentant le mot clé Java void.
Étant donné que la classe Void
ne peut pas être instanciée, la seule valeur que vous pouvez transmettre à une méthode avec un paramètre de type Void
, tel que handle(Void e)
, est null
.
C'est la version officielle des événements, mais pour ceux qui sont intéressés, malgré les affirmations contraires dans le javadoc de Void
, vous pouvez instancie en fait une instance de Void
:
Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
Void v = c.newInstance(); // Hello sailor!
Cela dit, j'ai vu Void
"utilement" utilisé comme type de paramètre générique lorsque vous voulez indiquer que le type est "ignoré", par exemple:
Callable<Void> ignoreResult = new Callable<Void> () {
public Void call() throws Exception {
// do something
return null; // only possible value for a Void type
}
}
Le paramètre générique de Callable
est le type de retour, donc quand Void
est utilisé comme ceci, c'est un signal clair aux lecteurs du code que la valeur retournée n'est pas importante, même si l'utilisation de l'interface Callable
est requise, par exemple si vous utilisez le framework Executor
.
Considérez l'API pour AsyncTask<T1, T2, T3>
de le Android , qui fournit trois crochets:
class AsyncTask<S, T, V> {
void doInBackground(S...);
void onProgressUpdate(T...);
void onPostExecute(V);
}
Lorsque vous étendez le type générique AsyncTask<T1, T2, T3>
vous pourriez ne pas être intéressé par l'utilisation de paramètres pour la progression et le résultat , donc votre implémentation ressemblera à:
class HTTPDownloader extends AsyncTask<URL, Void, Void> {
void doInBackground(URL... urls) {}
void onProgressUpdate(Void... unused) {}
void onPostExecute(Void unused) {}
}
et vous pouvez appeler ces méthodes avec un paramètre null
, car Void
ne peut pas être instancié.
Si Void
n'est pas réellement une instanciation d'un paramètre de type (où cela a évidemment un sens), il est également judicieux de déclarer une handle(Void)
si votre méthode handle
est soumise à un contrat extralinguistique qui dit que l'objet qui veut participer à un certain protocole doit implémenter une méthode de gestion à un argument, quel que soit le type d'argument réel. Maintenant, il peut y avoir une implémentation de cas spécial qui ne peut gérer que null
, il est donc logique de déclarer handle(Void)
pour une telle implémentation.