7
votes

Pourquoi Java ne supporte-t-il pas l'inférence de type pour les constructeurs?

E.g. Pour créer une arrayliste de chaînes, nous devons faire quelque chose comme xxx

alors qu'il devrait être capable de déduire le type de paramètre pour le constructeur afin que nous ne devons que taper Xxx

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.


7 commentaires

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 (); .


@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 (); . Quelle liste 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 () car la rvalue ne complique pas la lecture, alors que list list = nouvelle arrayliste (); 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 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 ArrayList Strings = New MyCustomarrayList (); , alors que nouvelle arrayliste <> (); `est clair.


7 Réponses :


2
votes

Cela peut être et c'est une fonctionnalité prévue pour l'inclusion dans JDK7 .


0 commentaires

22
votes

Il s'agit d'une amélioration Java 7 également appelée opérateur de diamants. La syntaxe sera la suivante: xxx

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

selon RÉM FORAX , le changement est déjà dans le référentiel mercurial.


3 commentaires

Bien que cela soit bon à savoir, cela ne répond pas à la question pourquoi la version actuelle ne le supporte pas .


@ 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".



1
votes

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.

Si vous voulez une inférence de type sur JVM, consultez Scala .


1 commentaires

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?



6
votes

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: xxx

Tout ce dont vous avez besoin est l'importation statique et supprimer l'espace entre Nouveau et ArrayList () :)

(l'importation statique serait à la listes classe, BTW. Il existe des méthodes similaires pour les cartes, etc.)


3 commentaires

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.



2
votes

Outre les fonctionnalités JDK7, je suppose que vous pouvez utiliser s'étend et super . xxx

vous ne seriez pas capable de déduire dans ces deux cas.


1 commentaires

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.



2
votes

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 .

Notez comment Robert a souligné que la syntaxe sera ceci: xxx

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.


2 commentaires

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 dois d'abord ajouter cela au début, je n'ai pas tellement de soin du mot-clé Var en C #, mais plus je peux l'utiliser et avec le type d'inférence des génériques et des types anonymes, tout devient très cohérent.



0
votes

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 objet tout autour.

Lorsque vous instaniez un nouveau ArrayListe , il aurait tort que le compilateur déduit le paramètre de type à partir de la classe d'instanciation ( ArrayList dans votre exemple), car il existe une classe avec ce nom exact et aucun paramètre de type (c'est le type brut , ArrayList ). Je suppose aussi que c'est pourquoi, dans Java 7, vous devrez ajouter <> à l'appel du constructeur pour indiquer au compilateur de déduire le type.

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 nouvelle arraylist () .

J'espère que cela est clair et que si je me trompe, quelqu'un peut me corriger. << hr>

Note latérale:

Aussi, méfiez-vous que la classe brute n'est pas la même que le type utilisant objet comme paramètre type: xxx

est valide, où comme xxx

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). >


1 commentaires

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 :)