E.g. Pour créer une arrayliste de chaînes, nous devons faire quelque chose comme alors qu'il devrait être capable de déduire le type de paramètre pour le constructeur afin que nous ne devons que taper p> Pourquoi le type ne peut pas être déduit de la même manière que les paramètres de type sont déposés pour des méthodes génériques. P> P>
7 Réponses :
Il s'agit d'une amélioration Java 7 également appelée opérateur de diamants. La syntaxe sera la suivante: la proposition officielle, accepté pour inclusion Dans la pièce de monnaie de projet est Inférence améliorée de type pour générique Création d'instance p> selon RÉM FORAX , le changement est déjà dans le référentiel mercurial. P> p>
Bien que cela soit bon à savoir, cela ne répond pas à la question pourquoi la version actuelle ne le supporte pas i>.
@ Joachim Sauer: Je ne peux pas offrir une réponse définitive sur la raison pour laquelle, mais en lisant les rapports de bogues référés par la proposition de diamant, je peux voir que la solution n'était pas bien comprise dans la période Java 5. Heck, les génériques sont un peu bouchés, même sans pousser l'inférence du constructeur dans Java 5.
@ Joachim ... Je crois que la phrase que vous recherchez est la "surveillance de la conception".
Le type peut être déduit, mais les auteurs ont juste décidé qu'il vaut mieux ne pas avoir de déduction de type du tout avoir une inférence limitée de type dans certains cas. P>
Si vous voulez une inférence de type sur JVM, consultez Scala . P>
Le problème est qu'il y a une certaine inférence! Les paramètres de type sur les méthodes paramétrés sont classés tout à fait! Pourquoi les mêmes règles ne peuvent-elles pas être appliquées à la création d'objets?
Comme d'autres personnes ont dit, c'est sur la liste pour Java 7 . Cependant, j'aimerais souligner que bibliothèque de collections Google Déjà en quelque sorte de soutien Pour divers collections, si vous êtes heureux d'utiliser des importations statiques. Par exemple, je répète fréquemment le code tel que: Tout ce dont vous avez besoin est l'importation statique et supprimer l'espace entre (l'importation statique serait à la Nouveau code> et ArrayList () Code>:) p> listes code> classe, BTW. Il existe des méthodes similaires pour les cartes, etc.) P> P>
Personnellement, je pense que c'est très laid. :)
C'est étrange lorsque vous le voyez pour la première fois, mais quand vous y êtes habitué, il peut réduire considérablement l'encombrement.
+1. J'utilise cela sans penser ces jours-ci, car Eclipse insérera l'importation lorsqu'il est autocompéqué, et j'ai des collections Google sur mon chemin de construction par défaut.
Outre les fonctionnalités JDK7, je suppose que vous pouvez utiliser s'étend em> et super em>. vous ne seriez pas capable de déduire dans ces deux cas. p> p>
L'inférence de type ne serait utilisée que si vous ne le précisiez pas manuellement (juste comme avec des méthodes dactylographiées en ce moment), donc cela ne rendrait donc pas cela impossible.
Vous voulez une raison pour laquelle le Java actuel ne le supporte pas.
Je ne peux que dire que Java prend généralement de petites étapes dans la mesure du possible. J'imaginerais qu'il y avait un peu de petit problème technique qu'ils n'étaient pas sûrs de devenir "droit" avant Java 7 - probablement quelque chose à faire avec absolument certain qu'il ne créerait pas de cas ambigu dans un code plus ancien ou non générique . P>
Notez comment Robert a souligné que la syntaxe sera ceci: p> remarque le vide <>? Je suppose que c'est pour désambiguïguer ce type d'inférence du code non générique ancien; C'est probablement juste quelque chose qu'ils n'ont pas pensé au début. P> p>
Yeh, je viens de lire les liens de Robert et le <> est de discrire des types bruts que vous dites.
Intéressant que ce type de direction opposée prise en C # où le type explicite est sur le côté droit et le type de la variable est déduit. Notez que dans la mise en œuvre de C # qui vous permet également de déduire des types de retour à partir d'autres appels de méthode sans avoir à définir explicitement le type. var cordes = nouvelle arrayliste
Je ne suis pas un super expert Java, je ne suis donc pas totalement sûr de ce que je vais dire. Voici mes pensées:
Comme Java implémente des génériques par effacement, pour chaque type générique, il existe un type brut sous-jacent. Si vous définissez un type générique, il y aura un type brut sous-jacent qui utilisera Lorsque vous instaniez un nouveau On pourrait argumenter que le compilateur Devrait instancier le type brut uniquement lorsque la classe de définition est le type brut, mais je pense que ce serait déroutant. Je pense que le compilateur doit déduire des expressions incomplètes qui seraient invalides sans contexte donné, ce qui n'est pas le cas pour la nouvelle arrayliste de J'espère que cela est clair et que si je me trompe, quelqu'un peut me corriger. p> << hr> Note latérale: p> Aussi, méfiez-vous que la classe brute n'est pas la même que le type utilisant est valide, où comme p> n'est pas. Dans le premier cas, le type brut peut être utilisé comme s'il s'agissait d'un type générique, mais dans le second cas, vous demandez de la contrevenance qui n'est pas disponible (pas si vous n'utilisez pas de caractères génériques). P> P> P> P> > objet code> tout autour. P> ArrayListe code>, il aurait tort que le compilateur déduit le paramètre de type à partir de la classe d'instanciation ( ArrayList ArrayList code>). Je suppose aussi que c'est pourquoi, dans Java 7, vous devrez ajouter <> code> à l'appel du constructeur pour indiquer au compilateur de déduire le type. P> nouvelle arraylist () code>. P> objet code> comme paramètre type: p>
J'ai eu envie de répondre à cette question car je pense qu'aucune des réponses (qui sont toutes excellentes!) Ici vraiment aborder la question initiale qui est pourquoi i> :)
Existe-t-il un but de demander "Pourquoi la langue ne peut-elle pas fonctionner Y"? La réponse est généralement "parce que cela n'a pas été conçu pour".
Pourquoi! Oh pourquoi! C'est l'une de mes plus grandes plaines sur la mise en œuvre des génériques en Java. Emballage du constructeur dans une méthode d'usine statique rend le type d'inférence de type comme un charme, alors pourquoi pas avec le constructeur!
@skaffman: True, mais la chose confuse est que l'inférence de type existe pour des méthodes paramétrées, de sorte que les règles et la complexité de la mise en œuvre existent déjà. Juste pas pour l'instanciation d'objet!
Pour moi, cela semble beaucoup plus naturel (et plus sûr) de déduire le type (y compris le paramétrage de type) de la rvalue plutôt que la lvalue. S'il ne s'agissait pas de fournir une interface sur la déclaration de champ, je serais à l'aise avec
ArrayList Liste = nouveau (); code>. @Cecil a un nom: Je ne vois pas comment vous pourriez faire quoi sauf si l'arrayliste est final. C'est presque la même chose avec
list x = nouveau (); code>. Quelle liste code> code> doit être utilisée? @Robert: ArrayList n'est pas abstrait et c'est tout ce qui compte, alors que la liste n'est pas, mais une interface. Si la lvalue n'est pas abstraite, écrire
nouveau () code> car la rvalue ne complique pas la lecture, alors quelist list = nouvelle arrayliste (); code> fournit le paramètre type sur Le lvalue, mais la mise en œuvre sur la rvalue, sans le paramètre de type. Je suis plus à l'aise avec C # 's var code> mot-clé. Si je me souviens bien, il y a aussi une arrayliste ungénère / non typée, ne compliquant pas beaucoup l'inférence, mais cela semble un peu douteux.@Cecil: Tant que la dérayListe n'est pas définitive, l'expression est ambiguë, car elle est légale d'écrire à la fois
ArrayList Strings = New ArrayList (); et Code> ArrayList Strings = New MyCustomarrayList (); , alors que code> nouvelle arrayliste <> (); `est clair.