2010-01-06 18 views
18

¿Alguna vez hay una diferencia entre un comodín ilimitado, p. <?> y un comodín delimitado cuyo límite es Object, p. Ej. <? extends Object>?Comodines ilimitados en Java

Recuerdo leer en alguna parte que había una diferencia en los primeros borradores de los genéricos, pero ya no puedo encontrar esa fuente.

Respuesta

18

Como punto de pedntry, existe una diferencia si la clase/interfaz/constructor/método declara una cota (aparte de extends Object).

interface Donkey<T extends Thing> { } 

... 
    Donkey<? extends Object> foo; // FAIL 
+0

¡Guau! Lo perdí por completo. – notnoop

+0

Hawtin == smrt. – orbfish

+2

el ejemplo compila en javac 7 – irreputable

-1

Todo en java con la excepción de las primitivas se extienden objeto, por lo que no, no habría diferencia. Autoboxing permite el uso de primitivas, por lo que podría decirse que todo en Java es un objeto.

4

De la experimentación parece que, por ejemplo, List<?> y List<? extends Object> son compatibles con la asignación en ambos sentidos, y un método que tiene una firma con uno de ellos puede anularse con una firma utilizando el otro. por ejemplo,

import java.util.List; 

class WildcardTest<T> { 
    public void foo(List<? extends T> bar) {} 
} 

class WildcardTest2 extends WildcardTest<Object> { 
    @Override 
    public void foo(List<?> bar) {super.foo(bar);} 
} 
-1

<? extends Object> es exactamente el mismo que <?>. Lo siento, no tengo una referencia a mano, pero ... lo es. :)

EDITAR: por supuesto, solo estaba pensando desde una perspectiva particular cuando dije eso. Ignora mi respuesta (que fue rechazada de manera bastante correcta) y ve las respuestas mejor calificadas para la historia real.

+0

Hola Kevin, te topamos bien. Gracias por mirar lo de Executors2, muy apreciado. :-) También, siéntete libre de mirar mi entrada revisada a "Un rompecabezas muy normal"; Me gustaría ver cuál es la respuesta "oficial" y si mi enfoque se considera "trampa". :-P –

+0

Oh, no puedo, porque aparentemente mi publicación fue eliminada. –

32

Desde un punto práctico para la mayoría de la gente, <? extends Object> es lo mismo que <?>, como todos han sugerido aquí.

Sin embargo, difieren en dos puntos muy pequeños y sutiles:

  1. las JVM (Java Virtual Especificación de la Máquina) tiene una especificación especial para los comodines no acotados, como ClassFileFormat-Java5 especifica que comodín sin límites se codifica como * , mientras codifica un comodín delimitado por objeto como +Ljava/lang/Object;. Tal cambio se filtraría a través de cualquier biblioteca que analice el bytecode. Los escritores del compilador tendrían que lidiar con este problema también. De revisions to "The class File Format"

  2. Desde el punto de vista de la fiabilidad, son diferentes. JLS 4.6 and 4.7 codifica List<?> como un tipo reificable, pero List<? extends Object> como un tipo borrado. Cualquier escritor de la biblioteca que agregue .isReifiable() (por ejemplo, mjc lib) necesita tener en cuenta eso, para adherirse a la terminología de JLS. De JLS 4.6 and 4.7.

+1

+1, ¡Gracias! ¡No lo sabía! :) – missingfaktor

2

Es complicado ...

Para cualquier tipo de variable T, la especificación dice http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4

Cada variable de tipo ... tiene un límite. Si no se declara límite para una variable de tipo, se asume Object.

Uno podría pensar que es verdad para los comodines también, y ? debe ser sólo una forma rápida para ? extends Object.

Sin embargo, al buscar a través de las especificaciones, no hay evidencia de que un comodín deba tener un límite superior (o un límite inferior). El "ilimitado" ? se trata consistentemente distinto de los comodines delimitados.

podríamos deducir de las reglas de tipificación, que List<?> y List<? extends Object> son subtipos de uno al otro, es decir, que son básicamente del mismo tipo.

Pero la especificación las trata por separado, sin embargo. Por ejemplo http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7List<?> es un tipo reifiable, pero no es List<? extends Object>, lo que significa

// ok 
    List<?>[] xx = {}; 
    // fail 
    List<? extends Object>[] yy = {}; 

    // ok 
    boolean b1 = (y instanceof List<?>); 
    // fail 
    boolean b2 = (y instanceof List<? extends Object>); 

No entiendo por qué sin embargo. Parece perfectamente correcto decir que un comodín debe tener un límite superior y un límite inferior, por defecto es Object y null type.

+0

[JLS8] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1) - ¿El comodín? extends Object es equivalente al comodín ilimitado? – ZhongYu

+0

javac8 - permite 'List [] ', pero no' instanceof List ' – ZhongYu