Me encuentro con un código Java como este:
public interface Foo<E> {}
public interface Bar<T> {}
public interface Zar<?> {}
¿Cuál es la diferencia entre los tres anteriores y cómo llaman a este tipo de declaraciones de clase o interfaz en Java?
Respuestas:
Bueno, no hay diferencia entre los dos primeros: solo usan nombres diferentes para el parámetro de tipo (
E
oT
).La tercera no es una declaración válida:
?
se usa como comodín que se usa cuando se proporciona un argumento de tipo , por ejemplo,List<?> foo = ...
significa que sefoo
refiere a una lista de algún tipo, pero no sabemos qué.Todo esto es genérico , que es un tema bastante importante. Es posible que desee conocerlo a través de los siguientes recursos, aunque, por supuesto, hay más disponibles:
fuente
T
yE
son solo identificadores. Podrías escribirKeyValuePair<K, V>
por ejemplo.?
Sin embargo, tiene un significado especial.Es más convención que cualquier otra cosa.
T
está destinado a ser un tipoE
está destinado a ser un Elemento (List<E>
: una lista de Elementos)K
es clave (en aMap<K,V>
)V
es Valor (como valor de retorno o valor asignado)Son totalmente intercambiables (a pesar de los conflictos en la misma declaración).
fuente
Las respuestas anteriores explican los parámetros de tipo (T, E, etc.), pero no explican el comodín, "?", O las diferencias entre ellos, así que abordaré eso.
Primero, para ser claros: los parámetros comodín y tipo no son lo mismo. Cuando los parámetros de tipo definen un tipo de variable (por ejemplo, T) que representa el tipo para un ámbito, el comodín no: el comodín simplemente define un conjunto de tipos permitidos que puede usar para un tipo genérico. Sin ningún límite (
extends
osuper
), el comodín significa "usar cualquier tipo aquí".El comodín siempre viene entre paréntesis angulares, y solo tiene significado en el contexto de un tipo genérico:
Nunca
o
Se vuelve más confuso donde se superponen. Por ejemplo:
Hay mucha superposición en lo que es posible con las definiciones de métodos. Los siguientes son, funcionalmente, idénticos:
Entonces, si hay superposición, ¿por qué usar uno u otro? A veces, honestamente es solo estilo: algunas personas dicen que si no necesita un parámetro de tipo, debe usar un comodín solo para hacer que el código sea más simple / legible. Una diferencia principal que expliqué anteriormente: los parámetros de tipo definen una variable de tipo (por ejemplo, T) que puede usar en cualquier otra parte del alcance; el comodín no. De lo contrario, hay dos grandes diferencias entre los parámetros de tipo y el comodín:
Los params de tipo pueden tener múltiples clases limitantes; el comodín no puede:
El comodín puede tener límites inferiores; los params tipo no pueden:
En lo anterior, se
List<? super Integer>
defineInteger
como un límite inferior en el comodín, lo que significa que el tipo de Lista debe ser Entero o un supertipo de Entero. El límite de tipo genérico está más allá de lo que quiero cubrir en detalle. En resumen, le permite definir qué tipos puede ser un tipo genérico. Esto hace posible el tratamiento de genéricos polimórficos. Por ejemplo con:Puede pasar un
List<Integer>
,List<Float>
,List<Byte>
, etc., paranumbers
. Sin delimitación de tipos, esto no funcionará, así son los genéricos.Finalmente, aquí hay una definición de método que usa el comodín para hacer algo que no creo que pueda hacer de otra manera:
numberSuper
puede ser una Lista de números o cualquier supertipo de Número (por ejemplo,List<Object>
), yelem
debe ser Número o cualquier subtipo. Con todos los límites, el compilador puede estar seguro de que.add()
es seguro.fuente
Una variable de tipo, <T>, puede ser cualquier tipo no primitivo que especifique: cualquier tipo de clase, cualquier tipo de interfaz, cualquier tipo de matriz o incluso otra variable de tipo.
Los nombres de parámetros de tipo más utilizados son:
En Java 7 se permite crear instancias de esta manera:
fuente
Los nombres de parámetros de tipo más utilizados son:
Verá estos nombres utilizados en la API Java SE
fuente
el compilador realizará una captura para cada comodín (p. ej., signo de interrogación en la Lista) cuando cree una función como:
Sin embargo, un tipo genérico como V estaría bien y lo convertiría en un método genérico :
fuente