Java peut souvent inférer des génériques en fonction des arguments (et même sur le type de retour, contrairement à C# par exemple).Génériques génériques déduits en retour type
Exemple: J'ai une classe générique Pair<T1, T2>
qui vient stocke une paire de valeurs et peut être utilisé de la manière suivante:
Pair<String, String> pair = Pair.of("Hello", "World");
La méthode of
ressemble à ceci:
public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
return new Pair<T1, T2>(first, second);
}
Très agréable. Toutefois, cela ne fonctionne plus pour le cas d'utilisation suivante, ce qui nécessite des caractères génériques: (. Remarquez le casting explicite de faire List.class
le type correct)
Pair<Class<?>, String> pair = Pair.of((Class<?>) List.class, "hello");
Le code échoue avec l'erreur suivante (fournie par Eclipse):
incompatibilité de type: ne peut pas convertir
TestClass.Pair<Class<capture#1-of ?>,String>
àTestClass.Pair<Class<?>,String>
Cependant, appelant explicitement le constructeur fonctionne toujours comme prévu:
Pair<Class<?>, String> pair =
new Pair<Class<?>, String>((Class<?>) List.class, "hello");
Quelqu'un peut-il expliquer ce comportement? Est-ce par conception? Est-ce voulu? Est-ce que je fais quelque chose de mal ou est-ce que j'ai trébuché sur une faille dans le design/bug dans le compilateur?
conjecture sauvage: la « capture # 1 de? » Semble en quelque sorte à laisser entendre que le caractère générique est rempli par le compilateur à la volée, ce qui rend le type un Class<List>
, et échouant ainsi la conversion (Pair<Class<?>, String>
-Pair<Class<List>, String>
) . Est-ce correct? Y a-t-il un moyen de contourner ce problème?
Par souci d'exhaustivité, voici une version simplifiée de la classe Pair
:
public final class Pair<T1, T2> {
public final T1 first;
public final T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
return new Pair<T1, T2>(first, second);
}
}
Il semble que le convertisseur voit la signature de "de" car il retourne une paire étend la classe,? étend la classe > type. Pour les classes finales, il semble assez intelligent pour réduire la partie extends, c'est pourquoi il ne se plaint pas sur la chaîne. –
Zed
Hmmm, intéressant. Merci de m'avoir reliée ici. – jjnguy
Cela fonctionne maintenant dans java8. Le type de cible est également consulté pour inferene. – ZhongYu