2011-10-14 10 views
11

Rzućmy następujące klasy Hierarchia:Błąd generyczny Java?

public class MyType { 
} 

public class MySuperclass<T extends MyType> { 
    protected Map<String, String> myMap = new TreeMap<String, String>(); 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

public class MySubclass extends MySuperclass { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); // <-- compilation error 
    } 
} 

Dlaczego tam jest błąd kompilacji w nadpisane metody MySubclass? Komunikat o błędzie "Niezgodność typu: nie można przekonwertować z obiektu na ciąg".

Interesującą rzeczą jest to, że bonusie błąd kompilacji, jeśli określenie klasy rodzajowych typ dla MySuperclass w MySubclass definicji:

public class MySubclass extends MySuperclass<MyType> { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

Może ktoś wyjaśnić to zachowanie? Uważam, że jest to błąd kompilatora Java.

Używam jdk1.6.0_24.

Odpowiedz

12

To nie jest błąd. Rozszerzając MySuperclass zamiast MySuperclass<MyType>, jesteś rozszerzenie surowy typMySuperclass, co oznacza, że ​​myMap będzie również od rodzaju Map zamiast Map<String, String>.

+1

dokładnie. To był jeden z "puzzlerów" Blocha. – Bozho

+0

A więc generics to wszystko czy nic? Jeśli używasz typu surowego, nie otrzymasz żadnych generycznych dla tego typu, nawet części, które w ogóle nie są zależne od 'T'? – Thilo

+2

Ale co ma ogólną definicję 'MySuperclass ** **' wspólnego z rodzajami "Map ** ** myMap"? Są to dwie różne definicje rodzajowe bez "połączenia" między nimi. Nie rozumiem tego. –

1

To naprawdę nierozsądne. Można to uznać za błąd w projektowaniu. Główną przyczyną jest decyzja o zachowaniu wstecznego kompatybilnego interfejsu API kolekcji, zamiast pozostawiania starego nienaruszonego i wprowadzania nowego generowanego interfejsu API. Ta decyzja jest technicznie nonsensem, a ich wyjaśnienia są śmieszne. Prawdziwym powodem tego jest prawdopodobnie Sun był zmuszony wypchnąć Java5, ale nie miał wystarczającej ilości zasobów, więc wzięli łatwą trasę (wymazanie). Jesteśmy tutaj, całkowicie spieprzeni. Ten system typu bękarta jest nie tylko problemem sam w sobie, ale stanowi także wielką przeszkodę dla wprowadzenia jakiejkolwiek nowej funkcji.