(para aclarar la cuestión, 'T' se refiere a un parámetro de tipo declarado en la clase)¿Por qué el método getInterfaces() de java.lang.Class devuelve Class <?> [] y no Class <? super T> []?
A modo de ejemplo, revise la siguiente aplicación:
public class TestClass {
interface InterfaceA{}
interface InterfaceB{}
interface InterfaceC{}
class ClassA implements InterfaceA, InterfaceB, InterfaceC{}
public static void main(String[] args){
Class<? super ClassA> superClass1 = ClassA.class;
Class<? super ClassA> superclass2 = InterfaceA.class;
Class<? super ClassA> superclass3 = InterfaceB.class;
Class<? super ClassA> superclass4 = InterfaceC.class;
for(Class<?> clazz : ClassA.class.getInterfaces()){
System.out.println(clazz.getName());
}
}
}
La salida es lo que uno esperaría :
TestClass$InterfaceA
TestClass$InterfaceB
TestClass$InterfaceC
por lo tanto, en base a este ejemplo anterior, podemos ver que el compilador reconoce que InterfaceA hace reúnen º e los límites del comodín, como lo hacen todas las otras interfaces.
Intuitivamente, yo esperaría que los siguientes son seguros, pero no lo es:
Class<? super ClassA>[] interfaces = ClassA.class.getInterfaces();
El compilador da una advertencia, porque la firma dice que vuelva Clase; sin embargo, el javadoc para la clase afirma lo siguiente:
Si este objeto representa una clase, el valor de retorno es una matriz objetos que contienen representan a todas las interfaces implementadas por la clase .
'Este objeto' se refiere en nuestro caso a ClassA
. Sobre la base de esta declaración, si llamamos:
ClassA.class.getInterfaces()
entonces sabemos que, lógicamente, que cada Class<?>
en la matriz devuelta contendrá una referencia a un tipo de súper ClassA
.
Como un punto adicional de referencia:
Desde el lenguaje Java de referencia, tercera edición:
Una clase implementa necesariamente todas las interfaces que sus directos superclases y superinterfaces directas hacen. Esta herencia (múltiple) de interfaz permite a los objetos soportar (múltiples) comportamientos comunes sin compartir ninguna implementación.
La lectura de este y otras partes de la especificación, yo creo que cualquier clase o interfaz implementada o exteneded por una clase T
caerían en los límites <? super T>
.
Editado:
Se ha sugerido que no hay ninguna razón concreta para mi pregunta. Voy a dar un ejemplo:
1 import java.util.Map;
2 import java.util.HashMap;
3
4 public class MapWrapper<T> {
5 private final Map<Class<?>, OtherClass<T,?>> map = new HashMap <Class<?>, OtherClass<T,?>>();
6
7 public <W> void addToMap(Class<W> type, OtherClass<T,? super W> otherClass){
8 map.put(type, otherClass);
9 }
10
11 public <W> OtherClass<T,? super W> getOtherClassForAnyInterface(Class<W> type){
12 if(type.getInterfaces()!=null){
13 for(Class<?> interfaceType : type.getInterfaces()){
14 // Here, a cast is necessary. It throws a compiler warning for unchecked operations (rightfully so)
15 OtherClass<T,? super W> otherClass = (OtherClass<T,? super W>)getOtherClassForInterface(interfaceType);
16 if(null!=otherClass){
17 return otherClass;
18 }
19 }
20 }
21 return null;
22 }
23
24
25 public class OtherClass<T,V> {}
26
27 }
El problema está en la línea 15. Hay que echar a <? super W>
para obtener el tipo correcto. La advertencia del compilador puede ser suprimida, pero ¿está justificada? ¿Hay algún escenario donde este lanzamiento no sea cierto?
La clase puede no tener tales métodos que usen realmente cualquier superclase de T, pero, al representar un tipo en sí mismo, pretende proporcionar información sobre los súper tipos. Si observa el método getSuperclass() de Class, su tipo de devolución es 'Clase super T>'. Siendo este el caso, parece incluso más apropiado que getInterfaces() regrese de manera similar a mí. Si estuvieran pensando, como sugiere, que la Clase nunca usaría ninguno de esos métodos accesibles al permitir el comodín delimitado, ¿por qué Class proporcionaría una superclase que se especifica como ' super T>'? –
sager
Probablemente es un error del diseñador de API. Estoy argumentando que no importa de todos modos. – irreputable
He agregado un caso concreto de uso de clase de esta manera. Está en la búsqueda en sí ahora. – sager