2012-03-20 27 views
6

Tengo una pregunta en dos partesgenéricos de Java comodines y sus limitaciones

mi libro estados este "Si no se especifica el carácter comodín sin un superior obligado, entonces sólo los métodos de tipo de objeto puede ser invocada en el valores del comodín tipo "

No tengo idea de lo que esto podría significar. ¿Qué significa esto?

¿Cuáles son las limitaciones en los tipos de comodines (ilimitados y acotados)? Por ejemplo, si tengo una referencia a MyClass<?> o MyClass<? extends SomeOtherClass>, ¿qué métodos no puedo llamar a través de esa referencia? No entiendo lo que el comodín me permite o no hacer, que probablemente sea el motivo por el que no entiendo la cita del libro.

I tienen un ejemplo para la segunda parte:

class SomeOtherClass 
{ 
[...] 
} 

class MyClass<T> 
{ 
[...] 
} 

class Test 
{ 
    public static void main(String[] arg) 
    { 
     MyClass<? extends SomeOtherClass> myClass = new MyClass<String>() // for instance what does the wild card reference limit me to in any way. In a general sence. 
    } 
} 
+0

¿Puede aclarar su pregunta con un ejemplo? –

Respuesta

9

comodines límites (superior e inferior) son a menudo obligatorio para colecciones y clases que regresan objetos de tipo parametrizado.

A menudo oirá hablar de PECS, lo que significa "Productor extiende, consumidor super". Le sugiero que lea the answer to this question, para evitar la duplicación de respuestas.

  • Para ser más precisos, cuando se define el comodín con <? extends TheClass>, entonces usted está diciendo al compilador que el objeto comodín es al menos del tipo TheClass. Por lo tanto, puede utilizar este objeto como una instancia de TheClass y llamar a cualquier método que este tipo proponga.

  • Ahora, cuando defina su comodín como <? super TheClass>, le está diciendo al compilador que su tipo de objeto de comodín está implementado o extendido por el tipo TheClass. Significa que el tipo de objeto puede no ser TheClass, pero que un objeto TheClass se puede usar como una instancia de su referencia comodín. Por lo tanto, no puede llamar nada en ese objeto, ya que su tipo solo se conoce en tiempo de ejecución, pero puede pasar el objeto a los métodos que esperan un objeto comodín.

Ejemplos:

private void foo(List<?> list) { 
    Object o = list.get(0); // ok 
    list.add(new Object()); // won't compile! 

    // you cannot add anything, and only extract Object instances 
} 

private void foo(List<? extends TheClass> list) { 
    Object o1 = list.get(0); // ok 
    TheClass o2 = list.get(0); // ok 
    list.add(new Object()); // won't compile! 
    list.add(new TheClass()); // won't compile! 

    // You are sure that the objects are of a subtype of TheClass, 
    // so you can extract TheClass instances safely. However, you cannot 
    // add anything to this list since its type is not known (may be 
    // different from TheClass, so the compiler does not allow anything). 
} 

private void foo(List<? super TheClass> list) { 
    Object o1 = list.get(0); // ok 
    TheClass o2 = list.get(0); // won't compile! 
    list.add(new Object()); // won't compile! 
    list.add(new TheClass()); // ok 

    // You are sure that the objects are of a type implemented by TheClass, 
    // so you can add any TheClass instances to the list. However, you cannot 
    // extract TheClass objects since the objects type may be just implemented 
    // by TheClass, but different. 
} 
+0

No entiendo lo que significa la declaración en mi libro, ¿puede explicarlo en el mismo contexto? – rubixibuc

+0

Agregué fragmentos de código para que pueda comprender. –

+0

En la oración, ¿qué significan los "métodos de tipo Objeto"? Ahí es donde estoy confundido. ¿Significa métodos de la clase Object? – rubixibuc

0

normal genérico;

ArrayList<Man> list= new ArrayList<Man>(); 
list.put(man); 
Man m = list.get(0); 

El uso de comodines con cota superior:

ArrayList<? extends Person> list= new ArrayList<? extends Person>(); 
list.put(man); //Man is a person.. 
Person p = list.get(0); 

El uso de comodines:

ArrayList<?> list= new ArrayList<?>(); 
list.put(man); 
Object o = list.get(0); 

Si utiliza el comodín no se puede saber el tipo genérico de ArrayList, por lo tanto, sólo se puede obtener de objetos fuera de la lista lo que significa que ha vuelto a utilizar ArrayLists a la antigua usanza sin genéricos ..

+0

Eso es lo que pensé que todo se supone que es el límite especificado, pero cuando lo probé, pude extraer no solo los objetos, sino el límite superior (del genérico, no el referene). digamos la clase genérica después del borrado de tipo. Entonces, si uso MyClass y el encabezado MyClass es igual a MyClass mi variable de MyClass podrá devolver SomeOtherClass si tiene sentido y solo esa clase. Entonces sería en ese caso que puedo extraer más que solo objetos de la clase Objeto – rubixibuc

+1

No, su segundo ejemplo no compilará, ya que su tipo de lista puede ser 'Mujer', que se extiende' Persona' pero no está relacionado ' Hombre'. Como el compilador no puede saber, no se compilará en la línea 2 (cuando se usa el método .put()). –

+0

La solución es usar 'super' en lugar de' extends' en este segundo ejemplo. Por lo tanto, el tipo de lista puede ser de cualquier tipo implementado por 'Person', por lo que un objeto' Man' se ajustará y el compilador lo aceptará. Ese es el paradigma 'PECS': cuando quieres consumir objetos (es decir, agregarlos a una lista), necesitas' super', no 'extends';) –

0

Por ejemplo, tiene <?extiende el comodín MyClass >. Esto significa que cualquier clase que coincida con este comodín puede ser de tipo MyClass o cualquiera de sus descendientes. Pero como lo único que sabemos es que es descendiente de MyClass, solo podemos garantizar que los métodos disponibles en la clase MyClass estén disponibles para invocar.

Para comodín con bo límite superior <? > el límite superior será clase de objeto. Y esto significa que todo lo que sabemos es que la clase amplía Object, por lo que solo los métodos que están garantizados para estar presentes en esta clase son los que se definieron en la clase Object.