2010-04-18 33 views
19

Estoy teniendo problemas para entender el siguiente artículo: http://www.ibm.com/developerworks/java/library/j-jtp01255.htmlgenéricos de Java covarianza

Bajo,

los genéricos no son covariantes

el autor afirma,

Debido En una lista, agregando un Flotar a él parece perfectamente legal. Pero si ln se muestran dentadas con li, entonces rompería la promesa de seguridad de tipos implícita en la definición de li - que se trata de una lista de números enteros, que es la razón por tipos genéricos no pueden ser covariante.

No puedo entender la parte donde dice "si hubiera alias con li". ¿Qué quiere decir el autor por alias? (¿Referencia?). El fragmento de código sobre la línea citada parece ilustrar QUÉ es ilegal en Java y no POR QUÉ. Sería muy útil para mí si alguien pudiera explicar con un ejemplo. Gracias de antemano.

+0

IIRC, tipos genéricos no son covariantes porque no podían cambiar cómo se implementaron/utilizados en versiones anteriores de Java (compatibilidad con versiones anteriores) matrices, lo hace sonar una campana a alguien? – Rhangaun

+0

@Skeptic, las matrices son un ejemplo de cómo podría ser una implementación genérica covariante: arrojaría excepciones de tiempo de ejecución. Java no puede hacer eso porque los genéricos se borran en el tiempo de ejecución, por lo que solo puede controlarlo limitando la covarianza. – Yishai

+0

@Yishai, ese problema con las matrices fue discutido por Steele en una presentación llamada "Growing a Language" que parece que no puedo encontrar ahora. – Rhangaun

Respuesta

39
List<Integer> li = new ArrayList<Integer>(); 
List<Number> ln = li; // illegal 
ln.add(new Float(3.1415)); 

En Java, Entero hereda de Número (java.lang.Number), por lo que de manera intuitiva, cualquier cosa que sea un entero (java.lang.Integer) es también un número, pero lo que el artículo señala es que con los genéricos no funciona de esa manera, porque teniendo en cuenta que Por ejemplo, podría terminar colocando un flotante (que es un número) en un List<Integer>, que es ilegal porque un flotante no es un número entero.

Conclusión: Los genéricos no son covariantes.

Nota: Te recomiendo que leas Effective Java (2nd Edition) Capítulo 5: Genéricos.

+0

Gracias. 8) Pensé que la explicación no tenía nada que ver con el fragmento de código. Tonto de mí. – soocracy42

+0

+1 para que el reco lea Effective Java. He estado escribiendo código durante muchos años, y recogí EJ hace un mes e inmediatamente aprendí 5 o 6 estrategias de gran importancia. –

+0

Este artículo también es inmensamente útil: https://www.ibm.com/developerworks/java/library/j-jtp01255/index.html –

8

Si pudiera hacer algo como esto:

List<Float> foo; 
List<Object> bar; 

foo = new ArrayList<Float>(); 
bar = foo; 

foo.add(1.0f); 
bar.add("Hello"); 

cosas irían muy mal. En este ejemplo, la barra es un alias para foo, y si pudiera hacerlo, perdería el tipo de seguridad que es la razón principal por la que existen los genéricos.

+0

Muchas gracias. No estaba seguro sobre la parte del alias. Esto confirma que mi suposición era correcta. – soocracy42

+0

¡Ah! Así que ahora "Hello" no solo está en 'bar' (lo que probablemente estaría bien), sino también en' foo'. Finalmente tiene sentido :) Supongo que entonces podría declarar un método de lanzamiento de lista, que debería copiar la lista, hm. –

-2
public class vechicle { 
void drive(){ 
} 
} 
class car extends vechicle{ 
     //Covariance 
    vechicle getObject(){ 
     return new car(); 
    } 
     //contravariance 
    car getmyObject(){ 
     return (car) new vechicle(); 
    } 
} 
+0

java.lang.ClassCastException se generará en 'return (car) new vechicle();' – Rembo