¿Qué significa el signo de interrogación en el parámetro de tipo de genéricos de Java? [duplicar]
Este es un pequeño fragmento de código tomado de algunos de los ejemplos que acompañan al Stanford Parser. He estado desarrollando en Java durante aproximadamente 4 años, pero nunca he tenido una comprensión muy clara de lo que se supone que indica este estilo de código.
List<? extends HasWord> wordList = toke.tokenize();
No me preocupan los detalles del código. Lo que me confunde es qué se supone que transmite exactamente la expresión genérica en inglés.
¿Alguien puede explicarme esto?
? extends HasWord
significa "Una clase/interfaz que se extiende HasWord
". En otras palabras, HasWord
él mismo o cualquiera de sus hijos... básicamente cualquier cosa que funcione con instanceof HasWord
plus null
.
En términos más técnicos, ? extends HasWord
es un comodín delimitado, tratado en el elemento 31 de Effective Java 3.ª edición , que comienza en la página 139. El mismo capítulo de la 2.ª edición está disponible en línea como PDF ; la parte sobre comodines acotados es el elemento 28 que comienza en la página 134.
Actualización: el enlace PDF se actualizó desde que Oracle lo eliminó hace un tiempo. Ahora apunta a la copia alojada en la Escuela de Ingeniería Electrónica y Ciencias de la Computación de la Universidad Queen Mary de Londres.
Actualización 2: entremos un poco más en detalle sobre por qué querrías usar comodines.
Si declaras un método cuya firma esperas que pases List<HasWord>
, entonces lo único que puedes pasar es un archivo List<HasWord>
.
Sin embargo, si dicha firma fuera List<? extends HasWord>
así, podría pasar una en List<ChildOfHasWord>
su lugar.
Tenga en cuenta que existe una diferencia sutil entre List<? extends HasWord>
y List<? super HasWord>
. Como lo expresó Joshua Bloch: PECS = productor-extiende, consumidor-super.
Lo que esto significa es que si estás pasando una colección de la que tu método extrae datos (es decir, la colección está produciendo elementos para que los use tu método), debes usar extends
. Si está pasando una colección a la que su método agrega datos (es decir, la colección consume elementos que crea su método), debe usar super
.
Esto puede parecer confuso. Sin embargo, puede verlo en List
el sort
comando (que es solo un acceso directo a la versión de dos argumentos de Collections.sort). En lugar de tomar un Comparator<T>
, en realidad se necesita un Comparator<? super T>
. En este caso, el Comparador está consumiendo los elementos del List
para reordenar la propia Lista.
Un signo de interrogación es un significante de "cualquier tipo". ?
solo significa
Cualquier tipo que se extienda
Object
(incluidoObject
)
mientras que su ejemplo anterior significa
Cualquier tipo que se extienda o implemente
HasWord
(inclusoHasWord
siHasWord
es una clase no abstracta)