Pourquoi les génériques en Java fonctionnent-ils avec les classes mais pas avec les types primitifs?
Par exemple, cela fonctionne bien:
List<Integer> foo = new ArrayList<Integer>();
mais ce n'est pas autorisé:
List<int> bar = new ArrayList<int>();
Réponses:
Les génériques en Java sont une construction entièrement au moment de la compilation - le compilateur transforme toutes les utilisations génériques en transtypages au bon type. Il s'agit de maintenir la compatibilité descendante avec les runtimes JVM précédents.
Ce:
devient (grossièrement):
Donc, tout ce qui est utilisé comme générique doit être convertible en Object (dans cet exemple,
get(0)
renvoie unObject
), et les types primitifs ne le sont pas. Ils ne peuvent donc pas être utilisés dans les génériques.la source
En Java, les génériques fonctionnent comme ils le font ... au moins en partie ... car ils ont été ajoutés au langage un certain nombre d'années après la conception du langage 1 . Les concepteurs de langage ont été contraints dans leurs options pour les génériques en devant proposer une conception qui était rétrocompatible avec le langage existant et la bibliothèque de classes Java .
D'autres langages de programmation (par exemple C ++, C #, Ada) permettent aux types primitifs d'être utilisés comme types de paramètres pour les génériques. Mais le revers de la médaille est que les implémentations génériques (ou types de modèles) de ces langages impliquent généralement la génération d'une copie distincte du type générique pour chaque paramétrage de type.
1 - La raison pour laquelle les génériques n'étaient pas inclus dans Java 1.0 était à cause de la pression du temps. Ils ont estimé qu'ils devaient faire sortir le langage Java rapidement pour saisir la nouvelle opportunité de marché présentée par les navigateurs Web. James Gosling a déclaré qu'il aurait aimé inclure des génériques s'ils en avaient eu le temps. À quoi le langage Java aurait-il ressemblé si cela s'était produit?
la source
En java, les génériques sont implémentés en utilisant "Effacement de type" pour une compatibilité descendante. Tous les types génériques sont convertis en objet au moment de l'exécution. par exemple,
sera vu à l'exécution comme,
le compilateur est responsable de fournir une distribution appropriée pour assurer la sécurité du type.
va devenir
Maintenant, la question est de savoir pourquoi "Object" est choisi comme type lors de l'exécution?
Pour info: le projet Valhalla tente de résoudre le problème ci-dessus.
la source
Les collections sont définies pour exiger un type qui dérive de
java.lang.Object
. Les types de base ne font tout simplement pas cela.la source
Selon la documentation Java , les variables de type générique ne peuvent être instanciées qu'avec des types de référence, pas des types primitifs.
Cela est censé venir en Java 10 dans le cadre du projet Valhalla .
Dans un article de Brian Goetz sur l' état de la spécialisation
Il existe une excellente explication de la raison pour laquelle les génériques n'étaient pas pris en charge pour les primitifs. Et comment il sera implémenté dans les futures versions de Java.
...
la source
Lors de la création d'un objet, vous ne pouvez pas substituer un type primitif au paramètre type. Quant au pourquoi de cette restriction, c'est un problème d'implémentation du compilateur. Les types primitifs ont leurs propres instructions de bytecode pour le chargement et le stockage sur la pile de machines virtuelles. Il n'est donc pas impossible de compiler des génériques primitifs dans ces chemins de bytecode séparés, mais cela compliquerait le compilateur.
la source