2012-10-06 36 views
6

Estaba revisando el código de otra persona el otro día y encontré una línea que generó cierta preocupación. Para simplificar, supongamos que tengo una Clase A genérica y una Clase B abstracta. ¿Se permite la siguiente instanciación y, de ser así, por qué?Generics wildcard instanceiation

Object obj = new A<? extends B>(); 

Yo personalmente nunca han visto una instancia como el de arriba, a pesar de una declaración como

A<? extends B> obj = null; 

sin duda mantener. Siempre he usado el comodín en genéricos para declarar los parámetros del método, por lo que es posible que no tenga la experiencia.

+0

¿qué versión de java usas? –

+0

relacionado si no está duplicado: http://stackoverflow.com/questions/9147129/creating-new-generic-object-with-wildcard y http://stackoverflow.com/questions/12200136/cannot-instantiate-type-in- generics? lq = 1 –

Respuesta

3

Actualmente new A<? extends B>() no se compila. Ha sido constantemente ilegal desde Java 5.

Pero supongo que su ejemplo original fue algo así como new A<X<? extends B>>(). Esto último es legal en versiones recientes de Java.

La idea es que, al crear una instancia de un objeto, el valor para los parámetros de tipo puede ser cualquier tipo de comodín. ? extends B es un tipo de comodín, por lo que no está permitido. Pero X<? extends B> no es un tipo de comodín, aunque tiene un tipo de comodín como componente. Entonces puedes decir legalmente llamar al new A<X<? extends B>>().

Las reglas tienen sentido si lo piensas de esta manera. En última instancia, es un subproducto de la regla más fundamental que un tipo de comodín como ? extends B no puede ser declarado tipo de un campo o variable. Si A se define como

class A<T> { 
    T value; 
} 

entonces el hipotético new A<? extends B>().value habría un campo declarado de tipo? extends B. Como eso es ilegal, también lo es la instanciación. Pero new A<X<? extends B>>() no tiene ese problema.

+0

Muy buena respuesta, pero no creo que el razonamiento en la segunda mitad tenga mucho sentido. Si una variable 'a' se escribe como' A ', eso no significa que' a.value' está * declarado * como '? extiende B' - 'value' se declara como' T' donde 'A' declara' T'. 'a.value' does * evaluate * to'? extiende B'. Vea mi respuesta a una pregunta similar [aquí] (http://stackoverflow.com/a/9147768/697449). –

+0

@PaulBellora Admitido, no estaba muy claro en la segunda parte. Lo que pretendo decir es que hay una diferencia entre el tipo putativo de _expression_ 'a.value' y el tipo declarado de la _variable_' a.value'. Tenga en cuenta que una variable es tanto un valor r como un valor l, por lo que si se le permite crear una variable/campo con un comodín, escriba '? extiende T' (o '? super T') sería una variable inherentemente discapacitada. No podría usarlo como un valor r, (l-value respectivamente). Ahora, eso es tolerable para una referencia ordinaria 'a', pero nunca para' this'. – Saintali