¿Cuál es el principio general de "compatibilidad de tipo de parámetro" (sea lo que podemos llamar)?
Class<Base> cls1 = new Derived().getClass(); // ERR
Class<? extends Base> cls2 = new Derived().getClass(); // OK
Class<? super Base> cl3 = new Derived().getClass(); // ERR
Class<Base> cls4 = new Base().getClass(); // ERR
Class<? extends Base> cls5 = new Base().getClass(); // OK
Class<? super Base> cls6 = new Base().getClass(); // ERR
Mi respuesta:
Class<Base> cls1
LHS en espera exactamente Class<Base>
en RHS => Class<? extends Derived>
es el error.
Class<? extends Base> cls2
según PECS significa que todo lo que recibimos de CLS2 (por iterador o (imaginar es que existe) métodos "get") es la base (por lo que podemos llamar a los métodos de base en lo que tenemos). Class<? extends Derived>
es Base en cualquier caso (ya sea derivadas o sus subclases). Por lo tanto, compila.
Class<? super Base> cls3
según PECS medios que siempre se puede añadir a la base por CLS3 (imaginar es que existe) método "add / put" - por lo que la colección contiene la base o su superclase. Class<? extends Derived>
nunca puede ser la base => Error.
Yo entiendo que los new Derived().getClass()
retornos Class<? extends Derived>
, igualmente new Base().getClass()
rendimientos Class<? extends Base>
.
Entiendo que List<? extends String> lst = new ArrayList<String>();
está bien y por qué.
Entiendo matriz de covarianza y tipos de retorno covariantes .
Sin embargo, el anterior conjunto de problemas de prueba me gana - No puedo formular reglas que mi razonamiento se guiará por.
PS PECS respuestas no me ayudan a causa principalmente ven el problema en términos de "puedo añadir o poner o ambos en una colección / objeto". El foco de mi pregunta es sobre la compatibilidad de las referencias.
Dada una expresión de tipo T
, expression.getClass()
los rendimientos Class<? extends T>
, porque expression
es o bien un T
o una subclase de T
. (En sentido estricto, es un Class<? extends |T|>
, donde ||
denota el borrado; pero eso es un detalle innecesario en el contexto de esta pregunta, donde ninguno de los valores de T
son genéricos).
Teniendo en cuenta este hecho, expression.getClass()
no es ni Class<T>
ni Class<? super T>
, de la misma manera que una List<? extends Number>
no es un List<Number>
o una List<? super Number>
.
No importa si something
es new SpecificSomething()
: que no es una Class<SpecificSomething>
, porque el hecho de que es una nueva instancia (y que está garantizado que ser exactamente una SpecificSomething
) no se tiene en cuenta: new SpecificSomething()
es una expresión de tipo SpecificSomething
, por lo que getClass()
devuelve una Class<? extends SpecificSomething>
.