web-dev-qa-db-fra.com

Pourquoi Java autorise-t-il l'attribution d'une valeur NULL à un Enum?

C'est plus une question de design. (Donc, pas de code. Je pourrais poster un code pour créer un Enum et l'assigner à null si vous voulez que je le fasse. :)) J'ai beaucoup réfléchi à cette question ces derniers temps, mais je ne peux trouver aucune bonne raison . Les constantes Enum sont implicitement statiques et finales. Enum est censé dire: "Je peux prendre une valeur d’une des constantes présentes en moi". Pourquoi autoriser Enum à avoir une valeur nulle?. Pourquoi ne pas implicitement définir par défaut la valeur de Enum sur Enum.DEFAULT ou Enum.None? N'est-ce pas une meilleure approche que de permettre à Enum d'être null?

41
TheLostMind

Tout d'abord, null signifie la non-existence d'une instance. Fournir une constante par défaut telle que DEFAULT ou NONE changera cette signification. Deuxièmement, pourquoi auriez-vous besoin de quelque chose par défaut pour représenter ce qui semble être inexistant? C'est le but de null. Fondamentalement, vous devez initialiser et stocker un objet supplémentaire, qui ne devrait même pas exister.

BTW, ce n'est pas un choix de langue. C’est à vous de décider comment vous allez mettre en œuvre votre enum. Vous pouvez fournir une autre constante comme DEFAULT ou UNKNOWN dans votre enum et éviter d'attribuer null à la référence dans votre code. Ceci est connu sous le nom Null Object Pattern . Mais en disant que l'affectation null devrait elle-même être une erreur du compilateur, je dirais, puisqu'un Enum est de toute façon compilé en un Class, il serait donc parfaitement correct d'utiliser null pour représenter la non-existence d'une instance.

L’utilisation de null dans switch-case constitue toutefois l’un des pièges de l’autorisation de enum. Le code ci-dessous lancera NPE:

public class Demo {
    enum Color {
        WHITE, BLACK;
    }

    public static void main(String[] args) {
        Color color = null;

        switch (color) {    // NPE here
        case WHITE: break;
        case BLACK: break;
        }
    }
}
40
Rohit Jain

Je pense que Enum.DEFAULT signifie que votre variable enum contient une valeur, mais que null n'en contient pas. Si c'est null, on peut interpréter qu'il n'a pas de valeur, vous ne pouvez pas y invoquer de méthodes non statiques, par exemple.

3
Philip Voronov

Vous pouvez ajouter un comportement à vos enums (Conception gérée par le domaine), par exemple, ajouter une méthode publique nommée prettyPrint () qui renvoie une chaîne basée sur votre valeur enum. Comment une valeur par défaut/nulle peut-elle fournir une implémentation de cette méthode personnalisée?

Si vous voulez représenter null avec une énumération, vous devrez l'expliciter en utilisant manuellement un modèle d'objet null avec une valeur NONE et une implémentation personnalisée pour prettyPrint () basée sur la valeur NONE.

2
zenbeni

Java permet à toute référence d'être nulle et les références aux énumérations ne sont pas si spéciales qu'un cas particulier doit être créé pour l'empêcher ou pour fournir une autre version de comportement déjà bien spécifiée et bien comprise. Null est déjà une valeur sentinelle parfaitement adéquate: nous n’avons pas besoin d’une autre valeur.

Aucune de vos suggestions n’est convaincante, car elles nécessiteraient l’ajout de fonctionnalités supplémentaires pour les prendre en charge.

En tout cas, il est plusieurs années trop tard pour commencer à débattre de la question.

2
user207421

Vieux, je sais. Je suis à moitié en Java.

Pourquoi autoriser Enum à avoir une valeur nulle?

Il y a peu de cas d'utilisation, je crois. Par exemple, nous devons initialiser une variable enum pour nous dire qu'elle ne fait pas vraiment partie de l'énum, ​​mais nous pouvons modifier sa valeur ultérieurement, de sorte qu'elle en fasse partie. S'il n'y avait aucun moyen d'initialiser une variable d'énumération avec null, nous polluerions la définition d'énumération. Donc, à mon avis, des champs tels que LibEnum.NONE désordonnent les bibliothèques. Par exemple, vous ne voulez pas que l'on utilise LibEnum.NONE comme paramètres de méthodes, entre autres.

Je l'ai trouvé utile dans mon scanner lexical, parmi les mots-clés et les ponctuateurs. Supposons que vous ayez un identifiant "blah". Vous voulez ensuite vérifier s'il s'agit d'un mot clé.

private Keywordv getKeywordValue(String id)
{
    switch (id.length())
    {
        case 2:
        {
            switch (id)
            {
                case "do": return Keywordv.DO;
                case "if": return Keywordv.IF;
                case "is": return Keywordv.IS;

                // ...
            }

            break;
        }

        // ...
    }

    return null;
}

Grâce à null, il est alors facile de vérifier si l'identifiant n'est pas un mot clé.

id == null

Sinon, nous devrions définir quelque chose comme Keywordv.__NULL

0
hydroper