Je me suis toujours demandé pourquoi Java ne faisait pas d'inférence de type étant donné que le langage est ce qu'il est et que sa machine virtuelle est très mature. Go's est un exemple de langage avec une excellente inférence et qui réduit le nombre de saisies. Existe-t-il une raison particulière pour que cette fonctionnalité ne fasse pas partie de Java?
44
Réponses:
Techniquement, Java utilise l' inférence de type lors de l'utilisation de génériques. Avec une méthode générique comme
Le compilateur analysera et comprendra que lorsque vous écrivez
Une chaîne va être renvoyée pour le premier appel et un entier pour le deuxième appel en fonction de ce qui a été entré en tant qu'argument. Vous obtiendrez la vérification appropriée lors de la compilation. De plus, en Java 7, on peut obtenir des déductions de types supplémentaires lors de l’ instanciation de génériques tels que
Java a la gentillesse de nous indiquer les crochets vierges. Maintenant, pourquoi Java ne prend-il pas en charge l’ inférence de type dans le cadre d’une affectation de variable? À un moment donné, il y avait une RFE pour l'inférence de type dans les déclarations de variable, mais elle était fermée en tant que "ne résoudra pas" car
Le contributeur qui a clôturé cette session a également noté que cela ne faisait que ressembler à un "non-java-like", ce avec quoi je suis du même avis. La verbosité de Java peut être à la fois une bénédiction et une malédiction, mais elle fait du langage ce qu’il est.
Bien entendu, ce RFE n’était pas la fin de cette conversation. Au cours de Java 7, cette fonctionnalité a de nouveau été prise en compte , et certaines implémentations de test ont été créées, notamment celle de James Gosling lui-même. Encore une fois, cette fonctionnalité a finalement été abattue.
Avec la sortie de Java 8, nous obtenons maintenant l'inférence de type en tant que partie de lambdas en tant que telle:
Le compilateur Java est capable d’examiner la méthode
Collections#sort(List<T>, Comparator<? super T>)
, puis l’interface de,Comparator#compare(T o1, T o2)
et détermine ainsifirst
etsecond
devraitString
permettre au programmeur de ne pas avoir à reformuler le type dans l’expression lambda.la source
First, the redundant type serves as valuable documentation - readers do not have to search for the declaration of getMap() to find out what type it returns
- oui, si c'est le cas,HashMap<String, Integer> map = foo.getMap()
je suis d'accord - en C #, je ne l'utilise généralement pasvar
, même si je le pouvais. Mais cet argument ne tient pas si c'estHashMap<String, Integer> map = new HashMap<String, Integer>()
. Ceci est une vraie redondance et je ne vois aucun avantage à écrire deux fois le nom du type. Et comment je bénéficierais ici d’une vérification croisée du compilateur, je ne comprends pas du tout.var
en Java me manque toujours .Humans benefit from the redundancy
est la vraie réponse à la question actuelle, car chaque justification que j'ai lue semble être une excuse gratuite, sans fondement et ridicule des concepteurs Java: C # et C ++ ont tous les deux la fonction, les concepteurs C # et C ++ ne sont pas moins compétents que Java, et tout le monde est heureux de l'utiliser. Qu'est-ce qui rendrait les développeurs Java différents des développeurs C # ou C ++? C'est pourquoi je suis d'accord avec @KonradMorawski: "C'est comme ça que les choses se passent ici" semble à nouveau être la vraie raison en coulisse de cela.Tout d’abord, l’inférence de type n’a rien à voir avec la maturité du moteur d’exécution, qu’il s’agisse d’un processeur âgé de 30 ans ou d’une VM si récente que les bits sont toujours brillants. tout tourne autour du compilateur.
Cela dit, il est autorisé pour les génériques. La raison pour laquelle il n'est pas autorisé pour les types non génériques semble être dû à la philosophie: rien n'empêche les concepteurs de l'ajouter.
Mise à jour: on dirait que java 10 le supporte - http://openjdk.java.net/jeps/286
la source
Autant que je sache, lors de la conception de Java au début des années 90, l'inférence de type n'était pas si populaire parmi les langages traditionnels (mais c'était déjà un concept très connu, par exemple en ML). Donc, je peux imaginer que l’inférence de type n’a probablement pas été prise en charge car Java était destiné aux programmeurs venant de C ++, Pascal ou d’autres langages traditionnels qui ne l’avaient pas (principe de moindre surprise).
En outre, l'un des principes de conception de Java est d'écrire explicitement les choses pour s'assurer que le programmeur et le compilateur ont la même compréhension du code: la duplication d'informations réduit les risques d'erreur. Bien sûr, il peut être une question de goût de savoir si saisir quelques caractères de plus mérite la sécurité supplémentaire apportée, mais telle était la philosophie de conception suivie pour Java: écrire des choses explicitement.
Je ne sais pas si Java obtiendra l'inférence de type à l'avenir, mais IMO serait une grande révolution pour le langage (comme l'a mentionné Glenn Nelson, il a été qualifié de "non-java-like"). nommer Java en faveur d'un nouveau nom.
Si vous souhaitez utiliser un langage JVM avec inférence de type, vous pouvez utiliser Scala.
la source
Je peux penser à quelques raisons possibles. La première est que le typage explicite est auto-documenté. Java en fait généralement une priorité par rapport à la concision. Une autre raison pourrait être dans les cas où le type est quelque peu ambigu. Comme quand un type ou un sous-type peut satisfaire une routine. Supposons que vous souhaitiez utiliser une liste, mais que quelqu'un se présente et utilise une méthode exclusive à ArrayList. Le JIT déduirait une ArrayList et continuerait même si vous vouliez une erreur de compilation.
la source
Let's say you want to use a List, but someone comes along and uses a method exclusive to ArrayList. The JIT would infer an ArrayList and carry on even if you wanted a compilation error
- Je ne comprends pas ce bit. L'inférence de type a lieu au moment d'instancier une variable, sans appeler de méthode. Pourriez-vous peut-être montrer un exemple de ce que vous vouliez dire?Cela va à l’encontre de la recommandation bien établie de déclarer les variables à l’aide de l’interface la plus générique qui répondra à vos besoins et de les initialiser avec une classe d’implémentation appropriée, comme dans
Efficacement,
est rien que le sucre syntaxique pour
Si vous le souhaitez, votre IDE peut le produire à partir de l'
new ArrayList<String>()
expression en "un clic" (refactor / create local variable), mais rappelez-vous que cela contredit la recommandation "utiliser les interfaces".la source