2012-03-12 40 views
8

Soy plenamente consciente de que las matrices genéricos no se pueden crear instancias como tales:¿Por qué puedo declarar una matriz genérica como una variable de instancia?

data = new Entry<K, V>[]; 

Esto dará lugar a un error:

Cannot create a generic array of Entry<K,V> 

Así que, ¿por qué se me permite declarar una variable de instancia que es una matriz de tipo genérico sin errores?

private Entry<K, V>[] data; 
+3

Al declarar el tipo genérico de una matriz, casi * solo * declara su * intención * de usarlo como tal. Como el compilador * no puede * verificar los tipos genéricos y puede * fácilmente * romper el sistema de tipos con tipos genéricos en las matrices, el compilador le dirá cuándo está realizando una operación que no puede verificar. La mejor solución: evite arreglos cuando desee que el compilador verifique la consistencia de su tipo. –

+0

Véase también [Genéricos FAQ] de Angelika Langer (http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#Can%20I%20create%20an%20array%20whose%20component%20type%20is%20a%20concrete% 20instantiation% 20of% 20a% 20parameterized% 20type?) – McDowell

Respuesta

4

En principio, el comentario de Joachim Sauer ya es su respuesta, sin embargo, me gustaría detallarlo un poco.

Sun (Oracle) conoce de un fenómeno llamado memoria de la contaminación, que siempre sucede si un genérico puntero apunta variables a un objeto de tipo incompatible. Esto se puede lograr, por ejemplo, con el siguiente código:

List<String> list = new ArrayList<String>(); 
List<Number> numberList = (List<Number>)(List)list; 

obviamente, usted comenzará a ver ClassCastExceptions, una vez que comience a trabajar con ese código. Esto fue perfectamente aceptable para Sun al diseñar Generics, porque se obtiene una conversión obligatoria RawType/Unchecked de advertencia. Cada vez que se emite esta advertencia, usted sabe que tiene un código que no está 100% verificado y que puede causar contaminación en la memoria.

El principio de diseño general en Generics es que todas las posibles contaminaciones de memoria se indican con dichas advertencias. Esta es la razón por la cual la creación de matrices genéricas está prohibida. Suponiendo que no era, esto es lo que podría suceder:

List<String>[] array = new List<String>[5]; 
Object[] oArray = array // this works without warning and has to for compatibility 
List<Object> oList = new ArrayList<Object>(); 
oArray[1] = oList; 

Tendrá la memoria de contaminación allí sin ningún aviso y por razones de compatibilidad, una advertencia no se puede generar. Esta es la razón por la que Sun decidió prohibir matrices de tipos genéricos. Sin embargo, es posible que se declaren las variables porque allí aparece la advertencia de conversión sin marcar y esto es todo lo que Sun quería: una advertencia si la contaminación puede ocurrir.

2

Porque el compilador y/o JIT necesita poder inferir los tipos genéricos.

Cuando intenta crear una instancia de Entry<K, V>[], el compilador no puede inferir los tipos K y V, por lo que no podría crear el objeto real (lo que significa que el compilador no puede encontrar el correcto constructor).

Pero, si usted tiene un miembro de tipo Entry<K, V>[] es sólo una referencia a algún tipo genérico.
El tipo correcto se deducirá cuando se use, de acuerdo con el tipo real que se le asignará. Y debido a que hace referencia a un tipo real, todos los métodos que invocan a los constructores anc se decidirán por el tipo al que se hace referencia.

Cuestiones relacionadas