web-dev-qa-db-fra.com

Pourquoi les collections Java ne peuvent-elles pas stocker directement des types Primitives?

Les collections Java ne stockent que des objets, pas des types primitifs; Cependant, nous pouvons stocker les classes wrapper.

Pourquoi cette contrainte?

102
JavaUser

C’était une décision de conception Java que certains considèrent comme une erreur. Les conteneurs veulent que les objets et les primitives ne dérivent pas d’Object.

C'est un endroit que les concepteurs .NET ont appris de la machine virtuelle Java et ont implémenté les types de valeur et les génériques, de sorte que la boxe est éliminée dans de nombreux cas. Dans CLR, les conteneurs génériques peuvent stocker des types de valeur dans le cadre de la structure de conteneur sous-jacente.

Java a choisi d’ajouter 100% de support générique au compilateur sans le support de la machine virtuelle Java. La JVM étant ce qu'elle est, ne supporte pas un objet "non-objet". Les génériques Java vous permettent de prétendre qu'il n'y a pas de wrapper, mais vous payez quand même le prix de performance de la boxe. Ceci est IMPORTANT pour certaines classes de programmes.

La boxe est un compromis technique, et j’ai le sentiment que ce sont des détails de mise en œuvre qui se glissent dans le langage. L'autoboxing est un sucre syntaxique de Nice, mais constitue toujours une pénalité de performance. Au contraire, j'aimerais que le compilateur m'avertisse quand il fait une liste automatique. (Pour autant que je sache, c'est peut-être maintenant, j'ai écrit cette réponse en 2010).

Une bonne explication sur SO à propos de la boxe: Pourquoi certaines langues ont-elles besoin de la boxe et de l’unboxing?

Et critiques des génériques Java: Pourquoi certains prétendent-ils que la mise en œuvre des génériques par Java est mauvaise?

Dans la défense de Java, il est facile de regarder en arrière et de critiquer. La JVM a résisté à l'épreuve du temps et constitue une bonne conception à bien des égards.

83
codenheim

Facilite la mise en œuvre. Étant donné que les primitives Java ne sont pas considérées comme des objets, vous devez créer une classe de collection distincte pour chacune de ces primitives (pas de code de modèle à partager).

Vous pouvez le faire, bien sûr, il suffit de voir GNU Trove , Apache Commons Primitives ou HPPC .

Sauf si vous avez des collections vraiment volumineuses, les frais généraux des wrappers importent peu pour que les utilisateurs s'en soucient (et lorsque vous avez des collections primitives vraiment volumineuses, vous voudrez peut-être consacrer des efforts à la création ou à la création d'une structure de données spécialisée. ).

15
Thilo

C'est une combinaison de deux faits:

  • Les types primitifs Java ne sont pas des types de référence (par exemple, une int n'est pas une Object)
  • Java utilise des caractères génériques en utilisant l’effacement de type des types de référence (par exemple, un List<?> est vraiment un List<Object> au moment de l’exécution)

Dans la mesure où ces deux conditions sont remplies, les collections Java génériques ne peuvent pas stocker directement les types primitifs. Pour plus de commodité, l’auto-sélection est introduite pour permettre aux types primitifs d’être automatiquement mis en boîte comme types de référence. Ne vous y trompez pas, cependant, les collections stockent toujours des références d’objet.

Cela aurait-il pu être évité? Peut-être.

  • Si une int est une Object, il n'y a aucun besoin de types de boîte.
  • Si les génériques ne sont pas terminés à l'aide de l'effacement de type, les primitives auraient pu être utilisées pour les paramètres de type.
11
polygenelubricants

Il y a le concept de boxe automatique et de déballage automatique. Si vous essayez de stocker une int dans un List<Integer>, le compilateur Java la convertira automatiquement en une Integer.

7
Jeremy

Ce n'est pas vraiment une contrainte, n'est-ce pas?

Déterminez si vous souhaitez créer une collection contenant des valeurs primitives. Comment écririez-vous une collection pouvant stocker int, float ou char? Très probablement, vous aurez plusieurs collections, il vous faudra donc une intlist et une charlist, etc.

Tirant parti de la nature orientée objet de Java lorsque vous écrivez une classe de collection, celle-ci peut stocker n’importe quel objet de sorte que vous n’avez besoin que d’une classe de collection. Cette idée, polymorphisme, est très puissante et simplifie grandement la conception des bibliothèques.

3
Vincent Ramdhanie

La raison principale en est la stratégie de conception Java . ++ 1) Les collections nécessitent des objets à manipuler et les primitives ne sont pas dérivées de object c'est donc peut-être l'autre raison… 2) Les types de données primitifs Java ne sont pas des types de référence pour ex. int n'est pas un objet.

Surpasser:-

nous avons le concept de boxe automatique et de déballage automatique. donc, si vous essayez de stocker des types de données primitifs, le compilateur convertira automatiquement cela en objet de cette classe de données primitive.

0
user5693566

Je pense que nous pourrions voir des progrès dans cet espace dans le JDK, éventuellement en Java 10, sur la base de ce JEP - http://openjdk.Java.net/jeps/218 .

Si vous voulez éviter les primitives de boxe dans les collections aujourd'hui, il existe plusieurs alternatives tierces. Outre les options tierces mentionnées précédemment, il existe également Eclipse Collections , FastUtil et Koloboke .

Une comparaison de cartes primitives a également été publiée il y a quelque temps sous le titre: Large HashMap overview: JDK, FastUtil, Goldman Sachs, HPPC, Koloboke, Trove . La bibliothèque GS Collections (Goldman Sachs) a été migrée vers la fondation Eclipse et constitue désormais Eclipse Collections.

0
Donald Raab