2010-04-27 11 views
185

¿Por qué los genéricos en Java funcionan con clases pero no con tipos primitivos?¿Por qué Java Generics no admite tipos primitivos?

Por ejemplo, esto funciona bien:

List<Integer> foo = new ArrayList<Integer>(); 

pero esto no está permitido:

List<int> bar = new ArrayList<int>(); 
+0

int i = (int) new Object(); compila bien sin embargo. –

Respuesta

194

genéricos en Java son un tiempo de compilación del todo constructo - el compilador convierte todos los usos genéricos en moldes al tipo correcto. Esto es para mantener la compatibilidad con versiones anteriores de los tiempos de ejecución de JVM.

Este:

List<ClassA> list = new ArrayList<ClassA>(); 
list.add(new ClassA()); 
ClassA a = list.get(0); 

consigue convertido en (más o menos):

List list = new ArrayList(); 
list.add(new ClassA()); 
ClassA a = (ClassA)list.get(0); 

Por lo tanto, cualquier cosa que se utiliza como genéricos tiene que ser convertible al objeto (en este ejemplo get(0) devuelve un Object) , y los tipos primitivos no lo son Entonces no pueden ser usados ​​en genéricos.

+0

Aclare que esto es solo para Java. – ChaosPandion

+31

En C# no hay problema con los tipos primitivos. – Danvil

+0

@ ChaosPandion: hecho – thecoop

30

En Java, los genéricos funcionan de la manera en que lo hacen ... al menos en parte ... porque se agregaron al lenguaje varios años después de que se diseñó el lenguaje . Los diseñadores de idiomas fueron constreñidos en sus opciones para genéricos al tener que idear un diseño que fuera retrocompatible con el idioma existente y la biblioteca de clases Java.

Otros lenguajes de programación (por ejemplo, C++, C#, Ada) permiten el uso de tipos primitivos como tipos de parámetros para genéricos. Pero la otra cara de esto es que las implementaciones de genéricos (o tipos de plantillas) de dichos lenguajes generalmente implican la generación de una copia distinta del tipo genérico para cada tipo de parametrización.


1 - La razón por la que los genéricos no se incluyeron en Java 1.0 se debía a que la presión del tiempo. Sentían que tenían que obtener el lenguaje Java lanzado rápidamente para llenar la nueva oportunidad de mercado presentada por los navegadores web. James Gosling ha declarado que le hubiera gustado incluir genéricos si hubieran tenido tiempo. No se sabe cómo se vería el lenguaje Java si esto hubiera sucedido.

5

Las colecciones se definen para requerir un tipo que deriva de java.lang.Object. Los tipos de línea simplemente no hacen eso.

+21

Creo que la pregunta aquí es "por qué". ¿Por qué los genéricos requieren objetos? El consenso parece ser que es menos una opción de diseño y más obstaculizar la compatibilidad con versiones anteriores. En mi opinión, si los genéricos no pueden manejar primitivos, eso es un déficit de funcionalidad.Tal como está, todo lo que implica primitivas debe escribirse para cada primitiva: en lugar del Comparador , tenemos Integer.compare (int a, int b), Byte.compare (byte a, byte b), etc. Esa no es una solución ! –

+0

Sí, los genéricos sobre los tipos primitivos serían una característica imprescindible. Aquí hay un enlace a una propuesta para él http://openjdk.java.net/jeps/218 – crow

1

Según Java Documentation, las variables de tipo genérico solo se pueden instanciar con tipos de referencia, no tipos primitivos.

Esto se supone que viene en Java 10 bajo Project Valhalla.

En Brian Goetz documento sobre State of the Specialization

Hay un excellent explanation acerca de la razón por la cual genérico no fueron apoyados por primitiva. Y, how it will be implemented en futuras versiones de Java.

Implementación borrada actual de Java que produce una clase para todas las instancias de referencia y no admite instancias primitivas. (Esta es una traducción homogénea, y la restricción de que los genéricos de Java solo pueden abarcar los tipos de referencia proviene de las limitaciones de la traducción homogénea con respecto al conjunto de códigos byte de la JVM, que utiliza códigos de bytes diferentes para operaciones en tipos de referencia frente a tipos primitivos). Sin embargo, los genéricos borrados en Java proporcionan tanto parametricity comportamiento (métodos genéricos) y parametricity de datos (ejemplificaciones primas y comodín de tipos genéricos.)

...

se eligió una estrategia de traducción homogénea, donde las variables de tipo genérico se borran a sus límites ya que están incorporadas en bytecode. Esto significa que, independientemente de si una clase es genérica o no, aún se compila en una sola clase, con el mismo nombre y cuyas firmas de miembro son las mismas. La seguridad de tipo se verifica en tiempo de compilación, y el sistema de tipo genérico no restringe el tiempo de ejecución. A su vez, esto impuso la restricción de que los genéricos solo podrían funcionar sobre los tipos de referencia, ya que Object es el tipo más general disponible, y no se extiende a los tipos primitivos.

Cuestiones relacionadas