2009-11-05 6 views
6

¿Puede alguien explicarme por qué el siguiente código no funciona?genéricos error: no aplicable para los argumentos

public class Test { 

interface Strategy<T> { 
    void execute(T t); 
} 

public static class DefaultStrategy<T> implements Strategy<T> { 
    @Override 
    public void execute(T t) {} 
} 

public static class Client { 
    private Strategy<?> a; 

    public void setStrategy(Strategy<?> a) { 
    this.a = a; 
    } 

    private void run() { 
    a.execute("hello world"); 
    } 
} 

public static void main(String[] args) { 
    Client client = new Client(); 
    client.setStrategy(new DefaultStrategy<String>()); 
    client.run(); 
} 
} 

Estoy recibiendo el siguiente error:

The method execute(capture#3-of ?) in the type Test.Strategy<capture#3-of ?> 
is not applicable for the arguments (String) 

Tengo que trabajar alterando el código de la siguiente manera:

public class Test { 

interface Strategy<T> { 
    void execute(T t); 
} 

public static class DefaultStrategy<T> implements Strategy<T> { 
    @Override 
    public void execute(T t) {} 

} 

public static class Client<T> { 
    private Strategy<T> a; 

    public void setStrategy(Strategy<T> a) { 
    this.a = a; 
    } 

    private void run(T t) { 
    a.execute(t); 
    } 
} 

public static void main(String[] args) { 
    Client<String> client = new Client<String>(); 
    client.setStrategy(new DefaultStrategy<String>()); 
    client.run("hello world"); 
} 
} 

pero quiero entender por qué el original enfoque no funcionó.

Respuesta

0

que no funciona debido a que su clase Client está escrito para no específica Strategy (Strategy<?>), pero en el método run(), se pasa un String (que sólo es correcta para Strategy<String>!). ¡Eso solo funcionaría si cambiaras el tipo a y el parámetro setStrategy() al tipo Strategy<String>!

11

La respuesta es simple: el comodín no vinculado no se puede utilizar. Simplemente significa "objeto desconocido".

No proporciona ninguna información informativa al compilador. "¿?" significa de cualquier tipo, por lo que en realidad es demasiado genérico para significar cualquier cosa.

Echa un vistazo aquí: http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html

Como se dijo:

Collection<?> c = new ArrayList<String>(); 
c.add(new Object()); // Compile time error 

Dado que no sabemos cuál es el tipo de elemento de c significa, no podemos añadir objetos a la misma. El método add() toma argumentos de tipo E, el tipo de elemento de la colección. Cuando el parámetro de tipo real es?, Significa algún tipo desconocido. Cualquier parámetro que pasemos para agregar debería ser un subtipo de este tipo desconocido. Como no sabemos qué tipo es, no podemos pasar nada. La única excepción es null, que es miembro de todo tipo.

EDITAR: no se preocupe, este es un malentendido normal de java comodín cuando comienza a usarlos. Es por eso que existen comodines delimitados (por ejemplo, <? extends Something>), de lo contrario el comodín genérico sería casi inútil ya que el compilador no puede hacer suposiciones sobre él.

Cuestiones relacionadas