2014-09-26 3 views
9

Я мог бы ослепить некоторых людей здесь, но я все равно выстрелю.Класс общего класса

Я знаю, что я могу сделать:

Class<Response> c = Response.class; 

Чтобы получить класс объекта. Если предположить, что объект ответа Response<T> я хочу сделать что-то вроде следующего

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

Моей полной проблемы:

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; 
    } 
} 

Но выше параметра не указан в задании. Теоретически правильный способ требует:

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(); 
    } 
} 

Но что генерирует ошибку пуха «не удается выбрать из параметризованного типа».

В качестве альтернативы я мог бы передать класс в конструкторе:

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

[Тип стирания] (http://docs.oracle.com/javase/tutorial/java/generics/erasure.html). Невозможно получить информацию во время выполнения о параметре общего типа, потому что это не так. после компиляции. Прохождение в классе явно является обходным решением. – khelwood

+0

Джексон предоставляет типы токенов для этого. –

+0

Я думаю, что вы не можете захватить общие параметры внутри класса, но вы можете захватить общие параметры в подклассе. Я думаю, что это может быть то, о чем говорит @SotiriosDelimanolis. – Jason

ответ

5

В комментарии предполагают, что нет такого понятия, как

Class<GenericType<GenericArgument>> 

Или, скорее, он не делает то, что вы могли бы думаю, что делает. Каждое объявление типа (класс, интерфейс, перечисление, примитив) получает один экземпляр Class, независимо от того, является он общим или нет.

Как таковой, даже если у вас есть ссылка типа Class<GenericType<ArgumentOne>> и другого типа Class<GenericType<ArgumentTwo>>, экземпляр, на который они ссылаются, будет таким же. Более того, не будет никакого способа запросить тип аргумента типа.

Вы, кажется, используете Jackson's ObjectMapper. Он предоставляет вид взлома для получения информации об типовом типе в виде токенов типа. Вы можете использовать экземпляр TypeReference или JavaType для представления общих типов. Примеры here и в других местах Интернета.

+0

Спасибо Сотири. В частности, для вышеизложенного я использовал 'new TypeReference >() {}' как параметр класса, который устанавливает и предоставляет тип. – Diolor

+0

@Diolor Осторожно с 'T' как аргумент типа, вы не предоставляете никакого конкретного типа. Джексон по-прежнему будет использовать свои настройки по умолчанию. Этот _hack_ работает только с конкретными типами, а не с переменными типа. –

+1

Ну ... да. Единственный способ для работы над этим «T» - передать постоянный тип в переменной, например. '@JsonDeserialize (as = User.class) private T response;' который является таким же, как 'new TypeReference >() {}'. Тупик. – Diolor

Смежные вопросы