119 votes

Pourquoi Map.of n'autorise-t-il pas les clés et les valeurs nulles?

Avec Java 9, la nouvelle usine de méthodes ont été introduites pour l' List, Set et Map interfaces. Ces méthodes permettent rapidement de l'instanciation d'un objet Map avec des valeurs dans une ligne. Maintenant, si nous considérons:

Map<Integer, String> map1 = new HashMap<Integer, String>(Map.of(1, "value1", 2, "value2", 3, "value3"));
map1.put(4, null);

Le ci-dessus est autorisé sans aucune exception, alors que si nous le faisons:

Map<Integer, String> map2 = Map.of(1, "value1", 2, "value2", 3, "value3", 4, null );

Il lance:

Exception in thread "main" java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:221)
..

Je ne suis pas en mesure d'obtenir, pourquoi null n'est pas autorisé dans le second cas.

Je sais HashMap peut prendre la valeur null comme une clé et une valeur, mais pourquoi a été que limitée dans le cas de la Carte.d'?

La même chose se produit dans le cas d' java.util.Set.of("v1", "v2", null) et java.util.List.of("v1", "v2", null).

117voto

Nicolai Points 17516

Comme d'autres l'ont souligné, l' Map contrat permet de rejeter les valeurs null...

[S]ome implémentations interdire null des clés et des valeurs [...]. De tenter d'insérer un inéligibles à la clé ou la valeur jette un décoché exception, typiquement NullPointerException ou ClassCastException.

... et la collection des usines (pas seulement sur les cartes) faire usage de.

Ils interdire null des clés et des valeurs. Les tentatives de créer avec null clés ou des valeurs en NullPointerException.

Mais pourquoi?

Permettant null dans les collections est désormais considérée comme une erreur de conception. Cela a une variété de raisons. Une bonne convivialité, où les plus éminents fauteur de trouble est - Map::get. Si elle renvoie null, il est difficile de savoir si la clé est manquante ou la valeur est null. Généralement parlant, les collections qui sont garantis null gratuit sont plus faciles à utiliser. Mise en œuvre-sage, ils ont aussi besoin de moins de revêtement spécial, rendant le code plus facile à maintenir et plus performant.

Vous pouvez écouter Stuart Marques de l'expliquer dans cet exposé, mais JEP 269 (celui qui a introduit les méthodes de fabrique) résume ainsi:

Null éléments, les clés et les valeurs seront rejetées. (Pas récemment introduit collections ont pris en charge les valeurs null.) En outre, interdisant les valeurs null offre des opportunités pour une plus compact représentation interne, l'accès plus rapide, et moins de cas particuliers.

Depuis HashMap était déjà dans la nature quand cela a été progressivement découvert, il était trop tard pour le changer sans casser le code existant, mais la plupart des dernières implémentations de ces interfaces (par exemple, ConcurrentHashMap) ne permettent pas de null de plus et les nouvelles collections pour l'usine méthodes ne font pas exception.

(J'ai pensé à une autre raison est que l'utilisation explicite null valeurs a été perçue comme une probable mise en œuvre d'erreur, mais j'ai eu que des mauvaises. C'était à propos de dupliquer des clés, qui sont illégaux en tant que bien.)

Donc, interdisant null avait certaines raisons techniques, mais il a également été fait pour améliorer la robustesse du code à l'aide de la création des collections.

16voto

Eugene Points 6271

Exactement - un HashMap est autorisée à stocker null, pas le Map retournée par la statique de l'usine de méthodes. Pas toutes les cartes sont les mêmes.

Généralement, pour autant que je sais que c'est une erreur, en premier lieu, à autoriser les valeurs null dans l' HashMap comme les clés, les nouvelles collections interdire la possibilité de démarrer avec.

Penser à l'affaire quand vous avez une Entrée dans votre HashMap , qui jouit d'une clé et d'une valeur == null. Vous obtenez, il retourne null. Quelle est la moyenne? Il dispose d'une cartographie de l' null ou il n'est pas présent?

En va de même pour un Key - hashcode d'une telle clé null a à un traitement particulier de tous les temps. L'interdiction des valeurs null pour commencer - rendre cela plus facile.

8voto

1615903 Points 3355

Alors que HashMap n'autoriser les valeurs null, Map.of ne pas utiliser un HashMap et lève une exception si l'un est utilisé comme clé ou une valeur, comme documenté:

La Carte.de() et de la Carte.ofEntries() statique usine méthodes fournissent un moyen pratique pour créer immuable cartes. La Carte des instances créées par ces méthodes ont les caractéristiques suivantes:

  • ...

  • Ils interdire null clés et de valeurs. Les tentatives de créer avec null clés ou des valeurs NullPointerException.

6voto

En permettant à des valeurs null dans les cartes a été une erreur. Nous pouvons le voir maintenant, mais je suppose que ce n'était pas clair lorsque l' HashMap a été introduit. NullpointerException est le plus commun bug vu dans le code de production.

Je pourrais dire que le JDK va dans le sens d'aider les développeurs à combattre les entrées en phase nationale de la peste. Quelques exemples:

  • Introduction d' Optional
  • Collectors.toMap(keyMapper, valueMapper) ne pas autoriser ni l' keyMapper ni l' valueMapper fonction pour renvoyer un null de la valeur
  • Stream.findFirst() et Stream.findAny() jeter des entrées en phase nationale si la valeur trouvée est - null

Ainsi, le refus de null dans la nouvelle JDK9 immuable collections (et la carte) va dans le même sens. Et nous devrions tous en être remercié pour cela!

5voto

GhostCat Points 83269

La différence majeure est: lorsque vous créez votre propre Carte de la "option 1" de la sorte ... alors vous êtes implicitement en disant: "je veux avoir la pleine liberté dans ce que je fais".

Ainsi, lorsque vous décidez que votre carte doit avoir une valeur null clé ou une valeur (peut-être pour les raisons énumérées ici), alors vous êtes libre de le faire.

Mais "option 2" est d'environ une commodité chose - probablement destiné à être utilisé pour les constantes. Et les gens derrière Java simplement décidé que: "lorsque vous utilisez ces méthodes pratiques, puis la carte résultante est nulle-libre".

Permettant null valeurs signifie que

 if (map.contains(key)) 

n'est pas le même que

 if (map.get(key) != null)

ce qui pourrait être un problème parfois. Ou plus précisément: c'est une chose à retenir lorsque vous traitez avec cette carte de l'objet.

Et juste une anecdotique soupçon pourquoi cela semble être une approche raisonnable: notre équipe de mise en œuvre de semblables méthodes pratiques nous-mêmes. Et devinez quoi: sans rien connaître de plans sur l'avenir de Java standard méthodes, à nos façons de faire exactement la même chose: ils reviennent immuable copie des données entrantes; et ils le jettent en place lorsque vous fournissez des éléments null. Nous sommes encore tellement stricte que lorsque vous passez dans le vide listes/cartes/... nous plaindre ainsi.

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