2010-09-01 14 views
6

(Jest to nieco nawiązanie do mojego previous question)Jak uzyskać wartość <?> dla obiektu Foo <?>?

Mam Foo<?> obiekt, foo. Foo<T> to interfejs.

Jak uzyskać wartość typu ukrytą za <?>?

Należy zauważyć, że to nie jest prosta, ponieważ foo może być, na przykład obiektu klasy Bar<String>, gdzie Bar<T> implements Foo<T> lub pewne klasy anonyomus wykonania interfejsu FloatFoo, gdzie FloatFoo extends Foo<Float>. Potrzebuję rozwiązania, które działa we wszystkich przypadkach.

góry dzięki :)

+0

Czy Foo jest Twoim własnym interfejsem? Czy możesz wdrożyć dodatkowe metody? – Arne

+0

Tak, pomyślałem o tym - metoda 'getType()' rozwiązałaby problem. Prawdopodobnie skończę z takim rozwiązaniem. – mik01aj

Odpowiedz

2

Ostateczne (a może najlepsze z możliwych) rozwiązanie: Odtworzono kod, więc nie jest potrzebny. Przesunąłem cały kod, który wymagał parametru typu do Foo, więc mogłem zapewnić odpowiednią implementację w klasie. Okazało się, że jest znacznie mniej kodu.

9

Nie jest to możliwe przy użyciu odbicia ponieważ Java rodzajowych ma problemu Type Erasure. W czasie wykonywania zostały usunięte typy, które zostały zdefiniowane dla ogólnej klasy Foo, więc użycie refleksji na tej klasie nie przyniesie jej ogólnego charakteru. Informacje tego typu są używane tylko w kompilacji dla bezpieczeństwa typu.

C# nie ma tego problemu i można uzyskać dostęp do templatyzowanego typu klasy.

This to przegląd różnic.

8

Cóż, krótko mówiąc, nie można.

Jednak można uzyskać wartość <?> podczas korzystania z FloatFoo.

Rzeczywiście, z tego, co pamiętam, leki generyczne nie są przechowywane w informacji o klasie.

Jednak podczas tworzenia podtypu (klasy lub interfejsu) typu generycznego należy zapamiętać informacje ogólne, ponieważ mogą one określać niektóre metody podpisu podtypu.

Jako przykład, jeśli Foo interfaceis zadeklarowane jako to:

public interface Foo<T> { 
    public T doIt(); 
} 

Posiadanie

public interface FloatFoo extends Foo<Float> 

Oznacza to interfejs ma

public Float doIt(); 

metody zadeklarowane.

W tym celu kompilator musi mieć informacje o typie. Informacje te zostaną odzwierciedlone w interfejsie API Reflect, ponieważ klasa super-klasy FloatFoo będzie miała powiązane z nią niektóre parametry Type. A przynajmniej to jest to, co pamiętam z nielicznych przypadków, w których spotkałem się z takimi przypadkami (lub opracowałem je, ponieważ czasem może to być obowiązkowe).

Ale będziesz miał znacznie pełniejsze informacje pod numerem Angelika's generics FAQ.

+0

Problem polega na tym, że 'getMethod (" doIt "). GetReturnType()' zwraca 'Object', a jeśli chciałbyś uruchomić metodę, aby zobaczyć, co powróciło, czasami otrzymasz obiekt podklasy, a czasami' null'. – mik01aj

+3

powiązane i może pomocne: http://www.artima.com/weblogs/viewpost.jsp?thread=208860 – Arne

+0

@ m01 Sztuczka interfejsu, o której wspomina Riduidel, nie zawsze działa. Zostało to wspomniane jako przykład niektórych danych, ale podstawowy problem nadal istnieje. Link wspomniany przez Arne odwołuje się do obejścia stworzonego przez Neala Gaffera, jednego z twórców kompilatorów Java. – linuxuser27

1

skończyło się tworząc getType() metody w interfejsie:

Class<T> getType(); 

Może to nie jest najbardziej eleganckie rozwiązanie, ale zdecydowanie najprostsza.

+1

To nadal nie działa, jeśli Twoja jest, powiedzmy, Lista . Najlepszym zwrotem jest List.class. Jeśli sytuacja stanie się tak złożona, spójrz na wzór "Super Typ Token": http://gafter.blogspot.com/2006/12/super-type-tokens.html –

Powiązane problemy