2013-08-15 12 views
41

Przyjęta odpowiedź na this question opisuje, jak utworzyć instancję klasy T w klasie Generic<T>. Obejmuje to przekazanie parametru Class<T> do konstruktora Generic i wywołanie metody newInstance z tego.Jak uzyskać atrybut ".class" z ogólnego parametru typu?

Nowa instancja Generic<Bar> zostaje utworzone, a parametr Bar.class jest przekazywana.

Co zrobić, jeśli parametr typ rodzajowy dla nowego Generic klasie nie jest jakiś znany klasa jak Bar ale sama jest rodzajowy parametr? Załóżmy, że mam inną klasę Skeet<J> i chciałem utworzyć nową instancję klasy Generic<J> z wnętrza tej klasy. Następnie, jeśli staram się przekazać w J.class otrzymuję następujący błąd kompilatora:

cannot select from a type variable. 

jest jakiś sposób obejścia tego?

Specyficzny fragment kodu wywołującego błąd dla mnie jest:

public class InputField<W extends Component & WidgetInterface> 
               extends InputFieldArray<W> 
{ 
    public InputField(String labelText) 
    { 
    super(new String[] {labelText}, W.class); 
    } 
    /* ... */ 
} 

public class InputFieldArray<W extends Component & WidgetInterface> 
                   extends JPanel 
{ 
    /* ... */ 
    public InputFieldArray(String[] labelText, Class<W> clazz) 
          throws InstantiationException, IllegalAccessException 
    { 
    /* ... */ 

    for (int i = 0 ; i < labelText.length ; i++) { 
     newLabel = new JLabel(labelText[i]); 
     newWidget = clazz.newInstance(); 
     /* ... */ 
    } 
    /* ... */ 
    } 
    /* ... */ 
} 

Błąd dzieje, bo nie mogę napisać W.class. Czy istnieje inny sposób przekazywania tych samych informacji?

+0

Twoje pytanie może bardziej jasne, jeśli umieścić przykład kodu (tj. ten, który uruchamia błąd kompilatora). –

+0

Ale musisz mieć nazwę klasy w 'Skeet ' prawy? Musisz przekazać tę klasę do konstruktora "Generic". Jeśli wyświetlasz aktualny kod, możemy Ci pomóc. –

+0

nie można używać klasy 'J.class 'z powodu [typu wymazania] (http://stackoverflow.com/questions/tagged/type-erasure). Ale można uzyskać konkretną zmienną 'Class' na' Skeet 'konstrukcji – RiaD

Odpowiedz

39

Korzystanie .class na parametr typu nie jest dozwolone - z powodu type erasure, W zostaną skasowane do Component przy starcie. InputField będzie trzeba także wziąć Class<W> od rozmówcy, jak InputFieldArray:

public InputField(String labelText, Class<W> clazz) 
{ 
    super(new String[] {labelText}, clazz); 
} 
+0

Bazując na danym typie łącza usuwania, typ ogólny zostanie zastąpiony przez typ 'Obiekt', ponieważ w tym przypadku nie jest podawane żadne ograniczenie. Więc ponieważ typ 'Class' jest podklasą' Object', myślę, że w tym przypadku nie będziemy mogli wywoływać '.class'. Ale co jeśli podana granica nie jest 'Obiektem' (jak '', mam na myśli to, że metoda '.class' powinna być nadal możliwa do wybrania w tym przypadku, jestem trochę zmieszany tutaj. @Paul Bellora – Dreamer

+0

@Dreamer '.class' nie jest metodą lub czymkolwiek, co można dynamicznie rozdzielić w środowisku wykonawczym. Jest to konstrukcja kompilacyjna używana do statycznego uzyskania obiektu' Class' reprezentującego jawny konkretny typ. –

8

W nie mogą być dostępne ze względu na typ skasowaniem. Powinieneś wymagać, aby Class<W> został przekazany do metody. Otrzymujesz obiekt klasy, a jego ogólny zapewnia, że ​​tylko W i bez podklasy jest przekazywana, z powodu kowariancji.

public InputField(String labelText, Class<W> cls) 
{ 
    super(new String[] {labelText}, cls); 
} 

odbędzie W.class ale nie WSubtype.class.

1

zrobiłem to tak:

To jest moja definicja klasy:

public class ManagerGeneric <T> { 

To jest moim sposobem:

// Get the type of generic parameter 
Type typeOfT = new TypeToken<T>(){}.getType(); 
// Deserialize 
T data = gson.fromJson(json, typeOfT); 
Powiązane problemy