web-dev-qa-db-fra.com

Quelle est la différence entre Void et aucun paramètre?

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?

59
Adam Lee

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.

41
Confusion

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.

65
Bohemian

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é.

14
Raffaele

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.

6
Marko Topolnik