Devez-vous définir une valeur null / unknown pour les énumérations Java?

Lorsque vous définissez une énumération pour quelque chose qui peut être “non défini” dans vos interfaces, devriez-vous

  • définir une valeur d’énumération distincte pour cela, ou
  • utilisez simplement enumValue = null pour ces situations?

Par exemple,

serviceX.setPrice (Price priceEnum)

enum Price { CHEAP, EXPENSIVE, VERRRY_EXPENSIVE, UNKNOWN } 

et priceEnum.UNKNOWN au besoin

ou

 enum Price { CHEAP, EXPENSIVE, VERRRY_EXPENSIVE } 

et priceEnum = null si nécessaire?

Avoir un petit débat à ce sujet. Quelques points qui me viennent à l’esprit:

  • Utiliser Price.UNKNOWN enregistre un code “if (price == null)”. Vous pouvez gérer toutes les valeurs de Price x dans un seul commutateur
  • En fonction de la technologie d’affichage, il peut être plus facile de localiser Price.UNKNOWN
  • en utilisant Price.UNKNOWN genre de cause “numéro magique” problème dans le code, IMO. Nous avons ici Price.UNKNOWN, ailleurs peut-être Color.UNDEFINED, Height.NULLVALUE, etc.
  • using priceValue = null est plus uniforme avec la façon dont les autres types de données sont gérés en Java. Nous avons Integer i = null, DomainObject x = null, Ssortingng s = null pour les valeurs inconnues également, n’est-ce pas?
  • Price.UNKNOWN vous oblige à décider si la valeur NULL est autorisée universellement pour tous les cas d’utilisation. Nous pouvons avoir la méthode Prix getPrice () qui peut renvoyer Price.UNKNOWN et setPrice (Price p) qui n’est pas autorisé à accepter Price.UNKNOWN. Puisque Price.UNKNOWN est toujours inclus dans les valeurs de l’énumération, ces interfaces semblent un peu impures. Je sais que priceValue = null a le même problème (vous ne pouvez pas définir dans l’interface si la valeur null est acceptée ou non) mais cela semble un peu plus propre et un peu moins trompeur (?)

C’est en fait un exemple d’application du modèle d’object nul . À mon humble avis, il est toujours préférable d’avoir un object factice plutôt que nul. Par exemple, vous pouvez append des méthodes factices à null-object plutôt que de disperser votre code avec des vérifications nulles partout. Très pratique.

De plus, le nom de l’ enum vous donne une sémantique supplémentaire: le prix est-il inconnu , indéfini , non fiable , pas encore connu ? Et qu’est-ce que cela signifie si le prix est nul ?

UPDATE: Comme le fait remarquer Aaron Digulla , le modèle d’object nul nécessite de la mémoire. Mais ce n’est pas vraiment le cas la plupart du temps. Dans l’implémentation traditionnelle, vous avez généralement un object singleton for Null utilisé partout car il n’y a pas besoin d’instances séparées. Cela devient encore meilleur avec les énumérations car vous obtenez la sémantique de singleton gratuitement.

Un autre point est que la référence null et la référence à un object occupent la même quantité de mémoire (disons 4 octets sur une machine 32 bits). C’est l’object référencé qui occupe de la mémoire supplémentaire. Mais s’il s’agit d’un singleton, il n’y a pratiquement pas de surcharge de mémoire ici.

Je dirais aller avec Price.UNKNOWN si c’est une valeur valide pour un prix.

Je suis d’accord avec les inconvénients de traiter des références nulles que vous mentionnez, et je pense qu’elles motivent suffisamment la décision.

Les nouveaux langages, prennent Scala par exemple (et certains plus anciens, Haskell) se séparent des références nulles et utilisent les options / peut-être les monades à la place … pour de bonnes raisons.

Cela dépend comment allez-vous utiliser cette enum. Si vous l’utilisez dans des instructions switch / case, cela n’a pas d’importance. Si vous créez une ou des méthodes dans l’énumération, vous devez définir INCONNU.

Par exemple, vous pouvez définir une méthode public abstract Icon icon();

dans votre enum et ensuite mettre en œuvre cette méthode pour chaque membre de Price. Vous voudrez probablement afficher le point d’interrogation pour le prix inconnu. Dans ce cas, implémentez simplement la méthode icon() qui crée l’icône appropriée.

Il y a le Enum-Switch-Null-Trap . Il semble donc que, comme pour toute propriété qui est un object, si elle n’existe pas, elle est null .

Couleur ou Hauteur serait utilisé dans la logique du programme. Ils ne peuvent pas gérer avec une couleur indéfinie. Un prix est une donnée utilisateur et peut être inconnu. La couleur peut être userdata sinon, mais pour être utilisée comme couleur dans le code, elles doivent être définies.

Donc, le prix peut être INCONNU (au lieu de NULL), couleur non (null peut indiquer une erreur).