uso usando salir recorrer para objetos metodos listas eliminar elementos datos componentes como boton almacenar agregar java generics

usando - jlist java metodos



¿Cómo se pueden agregar elementos a una colección genérica comodín? (5)

Use esto en su lugar:

1 public List<? extends Foo> getFoos() 2 { 3 List<Foo> foos = new ArrayList<Foo>(); /* Or List<SubFoo> */ 4 foos.add(new SubFoo()); 5 return foos; 6 }

Una vez que declaras foos como List<? extends Foo> List<? extends Foo> , el compilador no sabe que es seguro agregar un SubFoo. ¿Qué pasa si un ArrayList<AltFoo> ha sido asignado a foos ? Esa sería una tarea válida, pero agregar un SubFoo podría contaminar la colección.

¿Por qué obtengo errores de compilación con este código de Java?

1 public List<? extends Foo> getFoos() 2 { 3 List<? extends Foo> foos = new ArrayList<? extends Foo>(); 4 foos.add(new SubFoo()); 5 return foos; 6 }

Donde ''SubFoo'' es una clase concreta que implementa Foo, y Foo es una interfaz.

Errores que recibo con este código:

  • En la línea 3: "No se puede crear una instancia de ArrayList <? Extends Foo>"
  • En la línea 4: "El método add (captura # 1-of? Extends Foo) en el tipo List <captura # 1-of? Extends Foo> no es aplicable para los argumentos (SubFoo)"

Actualización: Gracias a Jeff C, puedo cambiar la Línea 3 para decir "new ArrayList <Foo> ();". Pero todavía estoy teniendo el problema con la Línea 4.


Lo siguiente funcionará bien:

public List<? extends Foo> getFoos() { List<Foo> foos = new ArrayList<Foo>(); foos.add(new SubFoo()); return foos; }


Tratar:

public List<Foo> getFoos() { List<Foo> foos = new ArrayList<Foo>(); foos.add(new SubFoo()); return foos; }

El constructor ArrayList genérico necesita tener un tipo específico para parametrizar, no puede usar el ''?'' comodín allí. Cambiar la creación de instancias a "new ArrayList <Foo> ()" resolvería el primer error de compilación.

La declaración de la variable ''foos'' puede tener comodines, pero como conoce el tipo exacto, tiene más sentido hacer referencia al mismo tipo de información allí. Lo que tienes ahora dice que los foos tienen algún subtipo específico de Foo, pero no sabemos cuál. No se permite agregar un SubFoo, ya que un SubFoo no es "todos los subtipos de Foo". Cambiar la declaración a ''List <Foo> foos ='' resuelve el segundo error de compilación.

Finalmente, cambiaría el tipo de devolución a ''List <Foo>'' ya que los clientes de este método no podrán hacer mucho con el valor devuelto como está definido actualmente. Raramente deberías usar comodines en los tipos de devolución. Utilice una firma de método parametrizada si es necesario, pero prefiera que los tipos acotados aparezcan solo en los argumentos del método, ya que eso deja al llamador que puede pasar tipos específicos y operarlos y en consecuencia.


Para tener una idea de cómo funcionan los genéricos, consulte este ejemplo:

List<SubFoo> sfoo = new ArrayList<SubFoo>(); List<Foo> foo; List<? extends Foo> tmp; tmp = sfoo; foo = (List<Foo>) tmp;

El problema es que no fue diseñado para variables locales / miembros, sino para firmas de funciones, por eso es tan desagradable.


Solo pensé en agregar a este hilo antiguo, al resumir las propiedades de los parámetros de la Lista instanciados con tipos o comodines ....

Cuando un método tiene un parámetro / resultado que es una lista, el uso de tipo instanciación o comodines determina

  1. Tipos de lista que se pueden pasar al método como argumento
  2. Tipos de lista que se pueden completar a partir del resultado del método
  3. Tipos de elementos que se pueden escribir en la lista dentro del método
  4. Tipos que pueden ser poblados al leer elementos de la lista dentro del método

Param / Tipo de devolución: List< Foo>

  1. Tipos de lista que se pueden pasar al método como argumento:
    • List< Foo>
  2. Tipos de lista que se pueden completar a partir del resultado del método:
    • List< Foo>
    • List< ? super Foo>
    • List< ? super SubFoo>
    • List< ? extends Foo>
    • List< ? extends SuperFoo>
  3. Tipos de elementos que se pueden escribir en la lista dentro del método:
    • Foo y subtipos
  4. Tipos que pueden rellenarse cuando se leen elementos de la lista dentro del método:
    • Foo y supertipos (hasta Object )

Param / Tipo devuelto: List< ? extends Foo> List< ? extends Foo>

  1. Tipos de lista que se pueden pasar al método como argumento:
    • List< Foo>
    • List< Subfoo>
    • List< SubSubFoo>
    • List< ? extends Foo>
    • List< ? extends SubFoo>
    • List< ? extends SubSubFoo>
  2. Tipos de lista que se pueden completar a partir del resultado del método:
    • List< ? extends Foo>
    • List< ? extends SuperFoo>
    • List< ? extends SuperSuperFoo>
  3. Tipos de elementos que se pueden escribir en la lista dentro del método:
    • ¡Ninguna! No es posible agregar
  4. Tipos que pueden rellenarse cuando se leen elementos de la lista dentro del método:
    • Foo y supertipos (hasta Object )

Param / Tipo devuelto: List<? super Foo> List<? super Foo>

  1. Tipos de lista que se pueden pasar al método como argumento:
    • List< Foo>
    • List< Superfoo>
    • List< SuperSuperFoo>
    • List< ? super Foo>
    • List< ? super SuperFoo>
    • List< ? super SuperSuperFoo>
  2. Tipos de lista que se pueden completar a partir del resultado del método:
    • List< ? super Foo>
    • List< ? super SubFoo>
    • List< ? super SubSubFoo>
  3. Tipos de elementos que se pueden escribir en la lista dentro del método:
    • Foo y supertipos
  4. Tipos que pueden rellenarse cuando se leen elementos de la lista dentro del método:
    • Foo y supertipos (hasta Object )

Interpretación / comentario

  • las necesidades de las personas que llaman externas dirigen el diseño de la declaración del método, es decir, la API pública (normalmente la consideración principal)
  • Las necesidades de la lógica de método interno impulsan cualquier decisión adicional sobre los tipos de datos reales declarados y construidos internamente (normalmente la consideración secundaria)
  • use List<Foo> si el código de la persona que llama siempre se centra en la manipulación de la clase Foo, ya que maximiza la flexibilidad para leer y escribir
  • use List<? extends UpperMostFoo> List<? extends UpperMostFoo> si podría haber muchos tipos diferentes de llamante, se centró en manipular una clase diferente (no siempre Foo) y hay una sola clase superior en la jerarquía de tipo Foo, y si el método es escribir internamente en la lista y la persona que llama la manipulación de la lista está leyendo. Aquí el método puede usar internamente List< UpperMostFoo> y agregarle elementos, antes de devolver List< ? extends UpperMostFoo> List< ? extends UpperMostFoo>
  • si podría haber muchos tipos diferentes de llamantes, enfocados en manipular una clase diferente (no siempre Foo) y si se requiere leer y escribir en la lista y hay una sola clase más baja en la jerarquía de tipos Foo, entonces tiene sentido usar List< ? super LowerMostFoo> List< ? super LowerMostFoo>