Могу ли я вызвать класс .class на общий тип в Java?
Мне было интересно, есть ли способ в Java сделать что-то вроде
Class c = List<String>.class;
Class c2 = List<Date>.class;
Мне нужно что-то подобное, чтобы создать карту, в которой хранится имя класса (с общим типом) и соответствующий объект, который я могу впоследствии найти. Например,
Map<Class, Object> dataMap = new HashMap<Class, Object>();
dataMap.put(c, listOfStrings);
dataMap.put(c2, listOfDates);
Не возможно ли это из-за стирания стилей во время выполнения?
Ответы
Ответ 1
Вы не можете этого сделать, но вы можете достичь своей общей цели, используя тот же подход, что и Guice с TypeLiteral
, Если вы уже используете Guice, я предлагаю вам использовать это напрямую - в противном случае вы можете создать свой собственный подобный класс.
По сути, идея заключается в том, что подклассы родового типа, которые задают аргументы типа, непосредственно сохраняют эту информацию. Итак, вы пишете что-то вроде:
TypeLiteral literal = new TypeLiteral<List<String>>() {};
Затем вы можете использовать literal.getClass().getGenericSuperclass()
и получить от него аргументы типа. TypeLiteral
сам не нужно иметь какой-либо интересный код (я не знаю, есть ли у него что-нибудь в Guice, по другим причинам).
Ответ 2
Нет, это невозможно. Вы даже не можете ссылаться на List<String>.class
в своем коде - это приводит к ошибке компиляции. Для List
существует только один объект класса, и он называется List.class
.
Не возможно ли это из-за стирания стилей во время выполнения?
Правильно.
Btw это общий тип, а не аннотированный тип.
Update
С другой стороны, у вас может быть что-то довольно близкое к вашей карте выше, путем настройки Josh Bloch типичного гетерогенного контейнера (опубликованного в Effective Java 2nd Ed., Item 29) немного:
public class Lists {
private Map<Class<?>, List<?>> lists =
new HashMap<Class<?>, List<?>>();
public <T> void putList(Class<T> type, List<T> list) {
if (type == null)
throw new NullPointerException("Type is null");
lists.put(type, list);
}
public <T> List<T> getList(Class<T> type) {
return (List<T>)lists.get(type);
}
}
Приведение в getList
не проверяется, предупреждая, но я боюсь, что мы не можем этого избежать. Однако мы знаем, что значение, хранящееся для класса X
, должно быть List<X>
, поскольку это гарантируется компилятором. Поэтому я считаю, что бросок безопасен (если вы играете по правилам, т.е. Никогда не вызываете putList
с простым неопределенным параметром Class
), поэтому его можно подавить с помощью @SuppressWarnings("unchecked")
.
И вы можете использовать его следующим образом:
Lists lists = new Lists();
List<Integer> integerList = new ArrayList<Integer>();
List<String> stringList = new ArrayList<String>();
...
lists.putList(Integer.class, integerList);
lists.putList(String.class, stringList);
List<Integer> storedList = lists.getList(Integer.class);
assertTrue(storedList == integerList);
Ответ 3
Это невозможно, поскольку вы пытаетесь.
Но вы можете украсить эти списки и создать вместо MyListDates
и MyListString
и сохранить их в hashmap