486 votes

Quel est le point de l’opérateur de diamant en Java 7 ?

Le diamant de l'opérateur dans java 7 permet le code suivant:

List<String> list = new LinkedList<>();

Cependant en Java 5/6, je peux simplement écrire:

List<String> list = new LinkedList();

Ma compréhension du type d'effacement est que ce sont exactement les mêmes. (Le générique est supprimé lors de l'exécution de toute façon). Donc ma question est, pourquoi s'embêter avec le diamant? Quelles nouvelles fonctionnalités / type de sécurité permet-il? Si il ne donne aucune nouvelle fonctionnalité pourquoi ils ne mentionnent comme une fonctionnalité? Est ma compréhension de cette notion erronée? Merci à toute personne qui peut m'éclairer.

535voto

ColinD Points 48573

Le problème avec

List<String> list = new LinkedList();

c'est que sur le côté gauche, vous utilisez le générique de type List<String> où sur le côté droit, vous êtes à l'aide de la crue de type LinkedList. Raw types en Java efficacement n'existent que pour la compatibilité avec les pré-génériques de code et ne doit jamais être utilisé dans le nouveau code, à moins que vous devez absolument.

Maintenant, si Java a les génériques de début et n'ont pas de types, tels que l' LinkedList, qui ont été initialement créés avant il avait des génériques, il aurait sans doute pu faire en sorte que le constructeur d'un type générique déduit automatiquement ses paramètres de type de la gauche de la cession, si possible. Mais il n'a pas, et il doit traiter les raw des types et des types génériques différemment pour assurer la compatibilité ascendante. Qui se laisse avoir besoin de faire un légèrement différent, mais tout aussi pratique, la façon de déclarer une nouvelle instance d'un objet générique, sans avoir à répéter ses paramètres de type... le diamant de l'opérateur.

En ce qui concerne votre exemple original d' List<String> list = new LinkedList(), le compilateur génère un avertissement pour cette mission parce qu'il doit. Réfléchissez à ceci:

List<String> strings = ... // some list that contains some strings

// Totally legal since you used the raw type and lost all type checking!
List<Integer> integers = new LinkedList(strings);

Les génériques existent pour fournir au moment de la compilation de protection contre de faire la mauvaise chose. Dans l'exemple ci-dessus, à l'aide de la crue de type signifie que vous n'obtenez pas de cette protection et obtenez une erreur lors de l'exécution. C'est pourquoi vous ne devriez pas utiliser des types.

// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);

Le diamant de l'opérateur, cependant, permet à la droite de l'affectation doit être défini comme un vrai générique instance avec le même type de paramètres que le côté gauche... sans avoir à saisir ces paramètres. Il vous permet de garder la sécurité des génériques avec presque le même effort que l'utilisation de la crue de type.

Je pense que l'essentiel à comprendre est que le raw (avec n <>) ne peuvent pas être traités de la même manière que les types génériques. Lorsque vous déclarez une crue de type, vous obtenez tous les avantages et la vérification de type de médicaments génériques. Vous devez également garder à l'esprit que les génériques sont d'un usage général, la partie du langage Java... ils ne s'appliquent pas uniquement à la non-arg constructeurs d' Collections!

40voto

Octavian Damiean Points 20620

Votre compréhension est un peu imparfait. Le diamant de l'opérateur est une fonctionnalité intéressante car vous n'avez pas à répéter vous-même. Il est logique de définir le type une fois lorsque vous déclarez le type, mais n'a tout simplement pas de sens pour définir de nouveau sur le côté droit. Le principe DRY.

Maintenant, pour expliquer tous les fuzz sur la définition des types. Vous avez raison que le type est retiré au moment de l'exécution, mais une fois que vous voulez récupérer quelque chose d'une Liste avec la définition de type de vous faire revenir, comme le type que vous avez défini lors de la déclaration de la liste sinon il perdrait toutes les fonctionnalités spécifiques et ont seulement les caractéristiques des Objets, sauf quand on avait jeté l'objet récupéré à son type d'origine, ce qui peut parfois être très difficile et entraîner une ClassCastException.

À l'aide de List<String> list = new LinkedList() , vous obtiendrez rawtype avertissements.

15voto

Roman Points 21807

Cette ligne provoque l’avertissement [désactivé] :

Ainsi, la question se transforme : pourquoi [désactivé] avertissement n’est pas automatiquement supprimé uniquement pour le cas quand la nouvelle collection est créée ?

Je pense, il serait beaucoup plus difficile tâche puis en ajoutant `` caractéristique.

UPD: Je pense aussi qu’il y aurait un désordre s’il était légalement d’utiliser des types de bruts « juste pour quelques petites choses ».

12voto

maaartinus Points 12510

En théorie, le diamant de l'opérateur permet de vous écrire plus compact (et lisible) du code par l'enregistrement répété les arguments de type. Dans la pratique, c'est seulement deux à confusion caractères plus vous donnant rien. Pourquoi?

  1. Pas sain d'esprit programmeur utilise des raw types dans le nouveau code. Ainsi, le compilateur pourrait se contenter de supposer que par écrit des arguments de type que vous voulez qu'il en déduire.
  2. Le diamant opérateur ne fournit aucune information de type, il est seulement dit que le compilateur, "ça va bien". Donc, en omettant de lui, vous pouvez ne pas faire de mal. En tout lieu où le diamant de l'opérateur est légal, il peut être "déduit" par le compilateur.

À mon humble avis, avoir une claire et simple de la façon de marquer une source de Java 7 serait plus utile que d'inventer de telles choses étranges. En tant marqué code raw types pourraient être interdits sans rien perdre.

Btw., Je ne pense pas que cela devrait être fait à l'aide d'une compilation de l'interrupteur. La version Java d'un fichier de programme est un attribut du fichier, pas d'option. À l'aide de quelque chose d'aussi trivial que

package 7 com.example;

pourraient le rendre clair (vous préférerez peut-être quelque chose de plus sophistiqué, y compris un ou plusieurs mots-clés de fantaisie). On pourrait même permettre de compiler les sources écrites pour les différentes versions de Java ensemble sans aucun problème. Il permettrait à l'introduction de nouveaux mots-clés (par exemple, "module") ou de faire tomber certains obsolètes fonctionnalités multiples (non-public non-classes imbriquées dans un seul fichier ou que ce soit) sans perdre de compatibilité.

8voto

axtavt Points 126632

Lorsque vous écrivez `` , compilateur génère un avertissement « uncheckée ». Vous pouvez l’ignorer, mais si vous avez utilisé pour ignorer ces avertissements vous risquez de manquer également un avertissement qui vous informe d’un problème de sécurité de type réel.

Ainsi, il est préférable d’écrire un code qui ne génère pas d’avertissement supplémentaire, et diamond opérateur vous permet de le faire d’une manière commode sans répétitions inutiles.

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