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

J’ai une classe qui définit deux méthodes surchargées

public void handle(Void e) protected void handle() 

De toute évidence, ils sont différents, surtout handle(Void e) est public .

Quelle est la différence entre ces deux?

Comment appeler la première méthode? J’utilise le handle(null) – est-ce correct?

La première fonction est fonction d’un seul argument, qui doit être fourni et ne peut valablement prendre la valeur null . Toute valeur autre que null ne sera pas compilée. La seconde fonction ne prend aucun argument et la valeur null ne comstack pas.

Void est une classe spéciale généralement utilisée uniquement pour la reflection – son utilisation principale est de représenter le type de retour d’une méthode vide. Du javadoc pour le Void :

La classe Void est une classe d’espace réservé instable pour contenir une référence à l’object Class représentant le mot-clé Java vide.

É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 réellement instancier une instance de Void :

 Constructor c = Void.class.getDeclaredConstructor(); c.setAccessible(true); Void v = c.newInstance(); // Hello sailor! 

Cela dit, j’ai vu Void “utile” comme un type de paramètre générique lorsque vous voulez indiquer que le type est “ignoré”, par exemple:

 Callable ignoreResult = new Callable () { 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 lorsque Void est utilisé comme ceci, il est clair pour les lecteurs du code que la valeur renvoyée n’est pas importante, même si l’utilisation de l’interface Callable est requirejse, par exemple si vous utilisez le cadre de l’ Executor

Considérez l’API AsyncTask du système Android , qui fournit trois AsyncTask d’ AsyncTask :

 class AsyncTask { void doInBackground(S...); void onProgressUpdate(T...); void onPostExecute(V); } 

Lorsque vous AsyncTask type générique AsyncTask vous n’êtes peut-être pas intéressé par l’utilisation de parameters pour les hooks de progression et de résultat . Votre implémentation ressemblera donc à ceci:

 class HTTPDownloader extends AsyncTask { void doInBackground(URL... urls) {} void onProgressUpdate(Void... unused) {} void onPostExecute(Void unused) {} } 

et vous pouvez appeler ces méthodes avec un paramètre null , puisque Void ne peut pas être instancié.

Si Void n’est pas en réalité une instanciation d’un paramètre de type (où il a évidemment un sens), il est également logique de déclarer un handle(Void) si votre méthode de handle est soumise à un contrat extralinguistique indiquant que l’object qui veut participer dans un certain protocole doit implémenter une méthode de descripteur à un argument , indépendamment du type d’argument réel. Maintenant, il peut y avoir une implémentation de cas particulier qui ne peut rien gérer d’autre que null , il est donc logique de déclarer handle(Void) pour une telle implémentation.