Java a menudo puede inferir genéricos basados en los argumentos (e incluso en el tipo de devolución, en contraste con, por ejemplo, C#).Genéricos de comodines inferidos en el tipo de retorno
Caso en cuestión: Tengo una clase genérica Pair<T1, T2>
que acaba almacena un par de valores y puede ser utilizado de la siguiente manera:
Pair<String, String> pair = Pair.of("Hello", "World");
of
El método se parece a esto:
public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
return new Pair<T1, T2>(first, second);
}
Muy bonito. Sin embargo, esto ya no trabaja para el siguiente caso de uso, lo que requiere comodines: (. Note la conversión explícita para hacer List.class
el tipo correcto)
Pair<Class<?>, String> pair = Pair.of((Class<?>) List.class, "hello");
El código de error con el siguiente error (siempre por Eclipse):
desajuste Tipo: no se puede convertir de
TestClass.Pair<Class<capture#1-of ?>,String>
aTestClass.Pair<Class<?>,String>
Sin embargo, una llamada explícita al constructor sigue funcionando como se esperaba:
Pair<Class<?>, String> pair =
new Pair<Class<?>, String>((Class<?>) List.class, "hello");
Puede alguien explicar este comportamiento? ¿Es por diseño? ¿Es buscado? ¿Estoy haciendo algo mal o tropecé con un error en el diseño/error en el compilador?
conjetura salvaje: la “captura # 1 de?” De alguna manera parece implicar que el comodín es rellenado por el compilador sobre la marcha, por lo que el tipo de un Class<List>
, y no así la conversión (de Pair<Class<?>, String>
a Pair<Class<List>, String>
) . ¿Es esto correcto? ¿Hay alguna manera de evitar esto?
Para completarlo, aquí es una versión simplificada de la clase 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);
}
}
Parece que el convertidor ve la firma de "de" cuando devuelve un par extiende clase,? extiende clase > tipo. Para las clases finales parece lo suficientemente inteligente como para reducir la parte de las extensiones, es por eso que no se queja en el String. –
Zed
Hmmm, interesante. Gracias por vincularme aquí. – jjnguy
Ahora funciona en java8. El tipo de destino también se consulta para inferenarse. – ZhongYu