2012-11-18 20 views
5
interface A { 
    String n(); 
} 
class B implements A { 
    @Override 
    public String n() { return "asdf"; } 
} 
interface C<T extends A> { 
    T m(T t); 
} 
class D implements C<B> { 
    @Override 
    public B m(B b) { 
     return b; 
    } 
} 

Class<C<? extends A>> x = D.class; 

jest błąd na ostatniej liniidlaczego działa ten typ wieloznaczny?

Type mismatch: cannot convert from Class<D> to Class<C<? extends A>> 

to wygląda perfekcyjnie do mnie, ale może jestem trochę brakuje subtelności, w jaki sposób pracować typu symbole wieloznaczne. Czy jest sposób, w jaki mogę zmienić typ na ostatniej linii? Muszę to odwołanie, ponieważ mam zamiar to zrobić później:

B b = new B(); 
A y = x.newInstance().m(b); 

Ma to również błąd

The method m(capture#1-of ? extends A) in the type C<capture#1-of ? extends A> is not applicable for the arguments (B) 

jednak, jeśli go używać bez symboli wieloznacznych i wychwytywania, to działa dobrze:

A z = D.class.newInstance().m(b); 

Niestety, jakoś utknąłem z tym teraz, każda pomoc byłaby doceniona.

edit: usunięty this. referencje

edit: X zmienił się

Class<? extends C<? extends A>> x = D.class; 

i to działa. jednak wciąż otrzymuję błędy na x.newInstance().m(b)

The method m(capture#2-of ? extends A) in the type Test.C<capture#2-of ? extends A> is not applicable for the arguments (B) 

Odpowiedz

6

Prawo, skupiając się tylko na ostatniej części.

jednak wciąż otrzymuję błędy na x.newInstance() m (b)

The method m(capture#2-of ? extends A) in the type 
Test.C<capture#2-of ? extends A is not applicable for the arguments (B) 

Rzeczywiście - i to ma sens. Ponieważ nic w kodzie nie oznacza, że ​​faktycznie masz C<B>. Wszystko, co kompilator wie, to: newInstance zwrócił instancję typu o typie, która implementuje C<X> dla z pewnym typem X, która implementuje A. Skąd wiedział, że to jest B?

Jeśli chcesz zadzwonić m(b), będziesz potrzebować C<B>, co oznacza, że ​​deklaracja musiałaby być

Class<? extends C<B>> x = D.class; 

W tym momencie metoda wywołanie kompiluje czysto. Nie jest jasne, co próbujesz osiągnąć, ani czy to będzie wystarczająco dobre dla ciebie - ale mam nadzieję, że to wyjaśnia, dlaczego dostaję błąd, który dostaję ...

+0

czy 'B implementuje A' chociaż? Mam 'B' w tym przykładzie, ale chcę, aby biblioteka pracy z' A''s. Biblioteka jest biblioteką preferencji lub konfiguracji. A to HasPreferences, a C jest serializowalną klasą Preference.więc będą podtypy każdego z podklasami C , co oznacza, że ​​C jest obiektem preferencji dla A. – aepurniet

+0

C otrzyma A, aby pobrać dane konfiguracyjne z. i zastosuje na nich także konfigurację. może istnieć wiele C dla A. (dlatego tak i templatowałem to w ten sposób, a nie na odwrót) – aepurniet

+0

@aepurniet: 'B' implementuje' A', ale parametr 'Cm' nie jest typu 'A' - jest typu' T'. 'D' może polegać na otrzymaniu instancji' B', a nie jakiejś innej implementacji 'A'. Właśnie dlatego powoduje problem. Nie ma nic w deklaracji "klasy > 'który wspomina' B' ... –

0

jego typ niebezpieczny (myślę , wyłącz te ostrzeżenia, aby uniknąć zanieczyszczenia adnotacji)

Class<? extends C> x = D.class; 
    B b = new B(); 
    A y = x.newInstance().m(b); 
    A z = D.class.newInstance().m(b); 

ale działa.

Powiązane problemy