tipo registro programar mostrar mientras hacer guardar google formulario filtro filtrada escribes datos como busqueda buscar buscador boton archivos java generics interface wildcard

programar - formulario de registro en java



Uso de un comodín genérico en lugar de una interfaz (5)

Si desea almacenar una matriz de objetos del tipo MyInterface , ¿los siguientes son aceptables y, de ser así, cuándo usaría la segunda forma sobre la primera?

i) Usar solo una interfaz: -

List<MyInterface> mylist = new ArrayList<MyInterface>();

ii) Usar un comodín genérico: -

List<? extends MyInterface> mylist = new ArrayList<? extends MyInterface>();

Editar:

Como las respuestas hasta ahora han señalado, el número ii no compilará. ¿Cuál es la diferencia entre i y un caso iii donde:

iii) Usar un comodín genérico solo en la referencia: -

List<? extends MyInterface> mylist = new ArrayList<MyInterface>();


El segundo no compilará. Imagina:

A implements MyInterface B implements MyInterface

Entonces, lo siguiente coincidiría con su segunda expresión, pero no compilará:

// incorrect List<A> mylist = new ArrayList<B>();

Corrección: incorrecta también :

List<? extends MyInterface> mylist = new ArrayList<MyInterface>();

En cierto sentido, compila, pero no puede agregar ninguna subclases de MyInterface a él. Confuso, pero correcto, después de leer la explicación. La misma razón: el comodín se puede ver, por ejemplo, como:

// I know this is not compileable; this is internal compiler "thinking". // Read it as "somewhere someone may instantiate an ArrayList<A> and pass // it down to us; but we cannot accept it as something that could be // potentially used as List<B>" List<A> mylist = new ArrayList<MyInterface>();

Entonces esto no funcionará

mylist.add(b);

y viceversa. El compilador se niega a hacer esas operaciones potencialmente incorrectas.

La opción que le permite agregar cualquier subclase de MyInterface a mylist es:

List<MyInterface> mylist = new ArrayList<MyInterface>();


La diferencia es que el segundo no compilará. No puede instanciar un parámetro de tipo con otro parámetro de tipo con límites.


Si desea almacenar los objetos de tipo MyInterface el mejor (y compilable) enfoque sería:

List<MyInterface> mylist = new ArrayList<MyInterface>();

Pero si desea utilizar en el parámetro de método, puede utilizar la opción 2 (tipo de comodín delimitado) para la flexibilidad API.

public void someMethod(List<? extends MyInterface> myInterfaces);

EDITAR:
El código anterior dará la API más flexible porque los tipos genéricos son invariables , por lo que si tiene -

public class A implements MyInterface { // some implementation }

y si someMethod tiene un tipo de parámetro List<MyInterface> entonces no podrá tomar la List<A> , esto obliga a los usuarios de API a crear una List con tipo MyInterface en el otro lado -
List<? extends MyInterface> List<? extends MyInterface> permitirá pasar List<A> a someMethod ... el cliente generalmente tiene una List<ActualObject> por lo que es más flexible proporcionar un parámetro que tomará cualquier implementación de MyInterface

Al mismo tiempo, no use tipos de comodines como tipos de devolución como

public List<? extends MyInterface> someMethod();

Si el usuario de una clase tiene que pensar en tipos de comodines, probablemente haya algo mal con la API de la clase.


usa información de tipo exacta y completa en las implementaciones.

ArrayList<MyInterface> mylist = new ArrayList<MyInterface>();


List<? extends MyInterface> List<? extends MyInterface> significa una lista de algún subtipo de MyInterface , pero no sabemos qué subtipo.

Como no sabemos qué subtipo se usa en realidad, no podemos poner ningún objeto en él (ya que no podemos asegurarnos de que sea un elemento de este subtipo).

Podemos sacar objetos de dicha lista y saber que es un objeto que implementa MyInterface , pero nada más.