150 votes

retourne un objet Void

Quelle est la manière correcte de renvoyer un Void lorsqu'il ne s'agit pas d'une primitive ? Par exemple, j'utilise actuellement null comme ci-dessous.

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something
        return null;
    }
}

1 votes

J'écris un interpréteur pour un format de fichier, en utilisant le modèle d'interpréteur, mais certaines expressions n'ont pas de valeurs de retour.

4 votes

Il n'y a aucun moyen d'instancier le type Void, donc si vous devez vraiment retourner quelque chose de ce type, null est votre seule option. Cependant, vous n'avez probablement pas besoin de la valeur retournée pour quoi que ce soit, donc null devrait convenir.

0 votes

Oui, c'était ma logique aussi - je me demandais juste s'il y avait un moyen plus sémantique.

168voto

Bozho Points 273663

La classe Void est une classe de remplacement non substantielle qui contient une référence à l'objet Class représentant le mot-clé Java void.

Ainsi, n'importe lequel des éléments suivants suffirait :

  • paramétrage avec Object et renvoyant new Object() o null
  • paramétrage avec Void et renvoyant null
  • paramétrage avec un NullObject de la vôtre

Vous ne pouvez pas faire cette méthode void et tout autre retour quelque chose . Puisque ce quelque chose est ignoré, vous pouvez retourner n'importe quoi.

2 votes

Alors quelle est la manière génériquement correcte d'obtenir un type de retour de void ?

4 votes

Si vous voulez retourner null comme void, vous devez le couler dans certains cas : (Void) null

2 votes

return (Void)null;

16voto

Erick G. Hagstrom Points 120

Java 8 a introduit une nouvelle classe, Optional<T> qui peut être utilisé dans de tels cas. Pour l'utiliser, vous devez modifier légèrement votre code comme suit :

interface B<E>{ Optional<E> method(); }

class A implements B<Void>{

    public Optional<Void> method(){
        // do something
        return Optional.empty();
    }
}

Cela vous permet de vous assurer que vous toujours obtenir une valeur de retour non nulle de votre méthode, même s'il n'y a rien à retourner. C'est particulièrement puissant lorsqu'il est utilisé en conjonction avec des outils qui détectent quand null peut ou ne peut pas être renvoyée, par exemple l'application Eclipse @NonNull y @Nullable annotations.

3voto

kap Points 471

Juste pour le plaisir, il y a bien sûr la possibilité de créer Void en utilisant la réflexion :

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something

        try {
            Constructor<Void> voidConstructor = Void.class.getDeclaredConstructor();
            voidConstructor.setAccessible(true);
            return voidConstructor.newInstance();
        } catch (Exception ex) {
            // Rethrow, or return null, or whatever.
        }
    }
}

Vous ne ferez probablement pas ça en production.

3voto

Jorn Points 5202

Si vous n'avez besoin de rien comme type, vous pouvez utiliser void. Cela peut être utilisé pour implémenter des fonctions ou des actions. Vous pourriez alors faire quelque chose comme ceci :

interface Action<T> {
    public T execute();
}

abstract class VoidAction implements Action<Void> {
    public Void execute() {
        executeInternal();
        return null;
    }

    abstract void executeInternal();
}

Ou bien vous pouvez omettre la classe abstraite, et faire le retour null dans chaque action qui ne nécessite pas une valeur de retour vous-même.

Vous pourriez alors utiliser ces actions comme ceci :

Étant donné une méthode

private static <T> T executeAction(Action<T> action) {
    return action.execute();
}

vous pouvez l'appeler comme

String result = executeAction(new Action<String>() {
    @Override
    public String execute() {
        //code here
        return "Return me!";
    }
});

ou, pour l'action void (notez que vous n'affectez pas le résultat à quoi que ce soit)

executeAction(new VoidAction() {
    @Override
    public void executeInternal() {
        //code here
    }
});

2 votes

En quoi est-ce différent de ce que j'ai déjà ? Cela renvoie toujours null, comme je l'ai suggéré.

0 votes

Pourquoi devriez-vous rendre autre chose ? Ce que j'essaie de dire, c'est que vous n'avez pas besoin de la valeur de retour, donc ce que vous retournez n'a pas d'importance. J'ai essayé de clarifier cela avec mon édition.

2voto

Il est possible de créer des instances de Void si vous changez le gestionnaire de sécurité, donc quelque chose comme ça :

static Void getVoid() throws SecurityException, InstantiationException,
        IllegalAccessException, InvocationTargetException {
    class BadSecurityManager extends SecurityManager {

        @Override
        public void checkPermission(Permission perm) { }

        @Override
        public void checkPackageAccess(String pkg) { }

    }
    System.setSecurityManager(badManager = new BadSecurityManager());
    Constructor<?> constructor = Void.class.getDeclaredConstructors()[0];
    if(!constructor.isAccessible()) {
        constructor.setAccessible(true);
    }
    return (Void) constructor.newInstance();
}

Évidemment, ce n'est pas très pratique ou sûr ; cependant, cela renverra une instance de Void si vous êtes en mesure de changer le gestionnaire de sécurité.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X