2009-11-05 27 views
6

Czy ktoś może mi wyjaśnić, dlaczego poniższy kod nie działa?Błąd ogólny: nie dotyczy argumentów.

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(); 
} 
} 

Dostaję następujący błąd:

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

mam go do pracy przez kod zmienia się następująco:

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"); 
} 
} 

ale chcę zrozumieć, dlaczego oryginał podejście nie działa.

Odpowiedz

0

To nie działa, ponieważ klasa Client jest napisane na żadnym konkretnym Strategy (Strategy<?>), ale w sposobie run(), mijamy String (która jest poprawna tylko dla Strategy<String>!). To zadziała tylko wtedy, gdy zmienisz typ a i parametr setStrategy() na typ Strategy<String>!

11

Odpowiedź jest prosta: niezwiązany symbol wieloznaczny nie może być użyty. Oznacza po prostu "obiekt znany".

To nie daje niczego informatywnego kompilatorowi. "?" oznacza jakiegokolwiek rodzaju, więc w rzeczywistości jest zbyt ogólnikowe, by cokolwiek znaczyć.

Spójrz tutaj: http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html

Jak stwierdzono:

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

Ponieważ nie wiemy, co typ element C oznacza, że ​​nie można dodawać obiekty do niego. Metoda add() pobiera argumenty typu E, typ elementu kolekcji. Gdy rzeczywisty parametr typu to?, Oznacza on pewien nieznany typ. Każdy parametr, który przekazujemy do dodania, musiałby być podtypem tego nieznanego typu. Ponieważ nie wiemy, co to za typ, nie możemy niczego przekazać. Jedyny wyjątek to null, który jest członkiem każdego typu.

EDYCJA: nie martw się, to normalne niezrozumienie java wildcard, kiedy zaczniesz ich używać. Dlatego istnieją ograniczone symbole wieloznaczne (np. <? extends Something>), w przeciwnym razie generyczny symbol wieloznaczny byłby prawie bezużyteczny, ponieważ kompilator nie może na nim żadnych założeń.

Powiązane problemy