Pourquoi ne peut-javac déduire de type générique arguments pour les fonctions utilisées comme arguments?
Dans l'exemple suivant, pourquoi le compilateur en mesure d'en déduire les arguments génériques pour le premier appel à Foo.create()
dans Foo.test()
, mais pas en mesure de le faire dans la seconde? Je suis à l'aide de Java 6.
public class Nonsense {
public static class Bar {
private static void func(Foo<String> arg) { }
}
public static class Foo<T> {
public static <T> Foo<T> create() {
return new Foo<T>();
}
private static void test() {
Foo<String> foo2 = Foo.create(); //compiles
Bar.func(Foo.create()); //won't compile
Bar.func(Foo.<String>create()); //fixes the prev line
}
}
}
(L'erreur de compilation est La méthode func(un non-sens.Foo) dans le type de non-sens.La barre n'est pas applicable pour les arguments (un non-sens.Foo)).
Remarque: je comprends l'erreur de compilation peut être fixé par la troisième ligne en test() - je suis curieux de savoir si il ya une limitation spécifique qui empêche le compilateur d'être en mesure de déduire le type. Il apparaît pour moi qu'il y est assez de contexte pour elle ici.
Il est concevable qu'il n'est pas possible d'être assez intelligent, mais je n'ai pas compris pourquoi, encore.
Il est probablement possible d'être assez intelligent, il n'est tout simplement pas.
OriginalL'auteur bacar | 2013-02-01
Vous devez vous connecter pour publier un commentaire.
De Java 7, la méthode de résolution de surcharge doit passer avant tout type de cible de l'information à partir de la méthode que vous appelez peut être pris en compte pour essayer d'en déduire le type de la variable
T
dans la déclaration defunc
. Il semble insensé, puisque nous pouvons tous voir que dans ce cas il y a une et une seule méthode nomméefunc
, cependant, il est mandaté par le JLS et est le comportement dejavac
à partir de Java 7.Compilation se déroule comme suit: tout d'Abord, le compilateur voit qu'il est en train de compiler un appel à une méthode statique de la classe Bar nommé func. Pour effectuer la résolution de surcharge, il doit savoir ce que les paramètres de la méthode est appelée. Alors que c'est un cas trivial, il doit toujours le faire, et jusqu'à ce qu'il a fait de sorte qu'il ne dispose d'aucune information sur les paramètres formels de la méthode disponible pour l'aider. Les paramètres réels sont constitués d'un seul argument, un appel à
Foo.create()
qui est déclaré comme étant de retourFoo<T>
. Encore une fois, sans critères de l'objectif, la méthode, il peut seulement en déduire que le type de retour est l'effacement deFoo<T>
qui estFoo<Object>
, et il le fait.Surcharge de la méthode de résolution échoue, car aucun des surcharges de
func
est compatible avec un paramètre réel deFoo<Object>
, et une erreur est émise à cet effet.C'est évidemment très regrettable puisque nous pouvons tous voir que, si l'information pouvait tout simplement le débit dans l'autre sens, à partir de la cible de l'appel de la méthode de retour vers le site d'appel, le type peut facilement être déduit et il n'y aurait pas d'erreur. Et, en fait, le compilateur de Java 8 peut le faire, et ne. Comme une autre réponse, ce richer type d'inférence est très utile pour les lambdas qui sont ajoutés dans Java 8, et pour les extensions à l'Api Java qui sont apportées afin de tirer parti des lambdas.
Vous pouvez télécharger une version pré-construction de Java 8 avec la JSR 335 lambdas de la précédente lien. Il compile le code en question sans les avertissements ou des erreurs.
OriginalL'auteur David Conrad