2014-09-26 18 views
9

Mogę zaślepić niektórych ludzi tutaj, ale i tak wystrzelę.Klasa ogólna klasa

wiem, że mogę zrobić:

Class<Response> c = Response.class; 

Aby uzyskać klasę obiektu. Zakładając, że obiekt Response jest Response<T> chcę zrobić coś jak na poniższym

Class<Class<User>> c = Response<User>.class; 

moje pełne problemu:

public class RequestHelper<T> extends AsyncTask<String, Response, T> { 

    @Override 
    protected T doInBackground(String... strings) { 
     ... 
     Response <T> r = objectMapper.readValue(result, Response.class); 
     return r .getResponse(); 
    } 
} 

//and 

public class Response <R> { 
    private R response; 
    public R getResponse() { 
     return response; 
    } 
} 

Ale przede parametru nie została określona w przydziale. Teoretycznie prawidłowy sposób wymagałby:

public class RequestHelper<T> extends AsyncTask<String, Response, T> { 

    @Override 
    protected T doInBackground(String... strings) { 
     ... 
     Response <T> r = objectMapper.readValue(result, Response <T>.class); 
     return r.getResponse(); 
    } 
} 

Ale to generuje błąd "Nie można wybrać typu sparametryzowanego".

Ewentualnie mogę przekazać w konstruktorze klasy:

public class RequestHelper<T> extends AsyncTask<String, Response, T> { 

    .... 
    public RequestHelper(Class<Class<T>> tClass){ 
     this.tClass = tclass; 
    } 

    @Override 
    protected T doInBackground(String... strings) { 
     ... 
     Response <T> r = objectMapper.readValue(result, tclass); 
     return r.getResponse(); 
    } 
} 

// where the init of the class would have been: 

new RequestHelper<User>(Response<User>.class); 
+3

[Usunięcie typu] (http://docs.oracle.com/javase/tutorial/java/generics/erasure.html) - Nie ma sposobu, aby uzyskać informacje w czasie wykonywania na temat ogólnego parametru typu, ponieważ onn istnieje po kompilacji. Przejście w klasie jawnie jest powszechnym sposobem obejścia tego problemu. – khelwood

+0

Jackson udostępnia tokeny typów. –

+0

Myślę, że nie można przechwytywać ogólnych parametrów w klasie, ale można przechwytywać ogólne parametry w podklasie. Myślę, że może to dotyczyć @SotiriosDelimanolis. – Jason

Odpowiedz

5

Jak tłumaczy komentarz, nie ma czegoś takiego jak

Class<GenericType<GenericArgument>> 

czy raczej nie robi co może myślę, że to robi. Każda deklaracja typu (klasa, interfejs, enum, prymityw) otrzymuje pojedynczą instancję Class, niezależnie od tego, czy jest ona generyczna czy nie.

Jako taka, nawet jeśli masz referencję typu Class<GenericType<ArgumentOne>> i inną z typu Class<GenericType<ArgumentTwo>>, instancja, do której się odwołują, będzie dokładnie taka sama. Co więcej, nie będzie absolutnie żadnego sposobu na zapytanie o typ argumentu typu.

Wygląda na to, że używasz Jackson'a ObjectMapper. Zapewnia on pewien rodzaj hakowania do uzyskiwania ogólnych informacji o typie w postaci tokenów typu. Można użyć instancji TypeReference lub JavaType do reprezentowania typów ogólnych. Przykłady here i gdzie indziej w Internecie.

+0

Dzięki Sotiri. W szczególności dla powyższego użyłem 'new TypeReference >() {}' jako parametru klasy, który ustawia i podaje typ. – Diolor

+0

@Diolor Ostrożnie z 'T' jako argumentem typu, nie podajesz żadnego konkretnego typu. Jackson nadal będzie używać swoich domyślnych ustawień. Ten _hack_ działa tylko z konkretnymi typami, a nie zmiennymi typu. –

+1

Cóż ... tak. Jedynym sposobem działania powyższego 'T' jest przekazanie stałego typu do zmiennej, np. '@JsonDeserialize (as = User.class) prywatna odpowiedź T;' która jest taka sama jak 'new TypeReference >() {}. Ślepy zaułek. – Diolor

Powiązane problemy