Как получить литерал класса из общего класса - PullRequest
9 голосов
/ 19 мая 2010

Существуют такие методы, которые требуют литералов класса в качестве аргумента.

Collection<EmpInfo> emps =  
  SomeSqlUtil.select(  
  EmpInfo.class,  
  "select * from emps");

или

GWT.create(Razmataz.class);

Проблема возникает, когда мне нужно предоставить общие специфические классы, такие как

EmpInfo<String>
Razmataz<Integer>

Следующий синтаксис будет неправильным

Collection<EmpInfo<String>> emps =  
  SomeSqlUtil.select(  
  EmpInfo<String>.class,  
  "select * from emps");

или

GWT.create(Razmataz<Integer>.class);

Потому что вы не можете использовать синтаксис, такой как

Razmataz<Integer>.class

Итак, как бы я мог выжать буквальный класс из

EmpInfo<String>
Razmataz<Integer>

чтобы я мог использовать их в качестве аргументов для методов, требующих литералов класса?

Дополнительная информация

Хорошо, я признаюсь, что спрашиваю это в первую очередь для GWT.

У меня есть пара GWT RPC интерфейса Разматаз. (FYI, интерфейс GWT RPC должен быть определен в парах сервер-клиент). Я планирую использовать одну и ту же пару интерфейсов для связи, будь то String, Integer, Boolean и т. Д.

GWT.create(Razmataz) для Razmataz<T> жалуется, что, поскольку я не указал T, компилятор GWT рассматривал его как Object. Тогда компилятор GWT не будет принимать класс Object. Он должен быть более конкретным, чем объект.

Так что, похоже, я не могу сказать GWT.create, что такое T, потому что литерал Class - это концепция времени выполнения, а generics - это концепция времени компиляции, верно?

Ответы [ 3 ]

7 голосов
/ 19 мая 2010

Цитата из Обобщения и коллекции Java , раздел 7.2:

Литералы класса также ограничены; даже синтаксически невозможно предоставить параметр типа для типа в литерале класса. Таким образом, следующий фрагмент недопустим:

class ClassLiteral {
  public Class<?> k = List<Integer>.class;  // syntax error
}

Действительно, грамматика Java затрудняет анализ фразы, подобной предыдущей, и может вызвать каскад синтаксических ошибок [...]

Эта проблема с синтаксисом приводит к нерегулярности. Везде, где требуется тип reifiable, вы можете предоставить необработанный тип (например, List) или параметризованный тип с неограниченными подстановочными знаками (например, List<?>). Однако для токенов классов вы должны указать необработанный тип; даже неограниченные символы не могут появиться. Замена List<Integer> на List<?> в предыдущем коде приводит к аналогичному каскаду ошибок.

Итак, у вас нет выбора, но вы можете использовать только необработанные типы в токенах классов, например

GWT.create(Razmataz.class);
3 голосов
/ 21 мая 2010

Кто-то оставил здесь короткий, но краткий ответ, который я собирался выбрать в качестве ответа. К сожалению, этот человек удалил этот ответ. Если этот человек был бы так любезен, опубликовать этот ответ для меня, чтобы выбрать. А пока позвольте мне заявить об этом ответе и о том, как я его использовал.

Это то, о чем я должен был подумать ,


Interface RazmatazString extends Razmataz<String>{}

GWT.create(RazmatazString.class);

Основываясь на удаленном ответе,

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

Abstract class Razmatazer{
.....

  Interface Razmataz<T>{
  // does a lot of RPC stuffs
  }

  Interface RazmatazAsync<T>{
  // does a lot of RPC stuffs
  }

  RazmatazAsync<?> razmatazAsyncRPC;
}

Концепция заключается не в создании экземпляра дескриптора razmatazAsyncRPC в базовом классе, а в производном классе.

Для T = String

StringRazmatazer extends Razmatazer{

  Interface RazmatazStringAsync extends RazmatazAsync<String>{}
  Interface RazmatazString extends Razmataz<String>{}

  razmatazAsyncRPC = GWT.create(RazmatazString.class);
}

В противном случае мне пришлось бы повторить ~ 100 строк кода, ~ 50 каждая для Razmataz и RazmatazAsync, для различных T параметрических значений String, Map, Boolean, Integer и т. Д.

Основная предпосылка для преодоления этого препятствия была - мне лень повторять эти строки.

3 голосов
/ 19 мая 2010

Вы не можете.

Использовать небезопасный состав:

Collection<EmpInfo<String>> emps = 
     (Collection<EmpInfo<String>>) someMethod(EmpInfo.class);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...