#java #generics #type-erasure
#java #общие сведения #удаление типа
Вопрос:
Я пытаюсь выяснить, возможно ли получить тип объекта для универсального класса во время выполнения в Java.
Пример:
public class Member<T> {
private T id;
private T complexityLevel;
// constructor
public Member(T id, T complexityLevel) {
this.id = id;
this.complexityLevel = complexityLevel;
}
// getters and setters goes here
}
Тестирование..
public class TestDrive {
public static void main(String[] args) {
Member<String> memberString = new Member<String>("1", "100");
Member<Integer> memberInteger = new Member<Integer>(1, 100);
Member<Double> memberDouble = new Member<Double>(1.0, 100.00);
List<Member<?>> members = new ArrayList<>();
members.add(memberString);
members.add(memberInteger);
members.add(memberDouble);
for (Member<?> aMember : members) {
if (aMember.getClass().isInstance(String.class))
System.out.printf("String member is found with id: " aMember.getId());
else if (aMember.getClass().isInstance(Integer.class))
System.out.printf("Integer member is found with id: " aMember.getId());
else if (aMember.getClass().isInstance(Double.class))
System.out.printf("Double member is found with id: " aMember.getId());
}
}
}
Возможно ли получить классы-оболочки ( String
, Integer
, Double
и т.д.) для объектов Member
класса во время выполнения?
Ответ №1:
Вы не можете определить общие типы во время выполнения из-за стирания типов. Для того, чтобы эта информация была сохранена после удаления, Member<T>
необходимо будет взять Class<T>
объект в его конструкторе и удерживать его:
public class Member<T> {
public final Class<T> type;
private T id;
private T complexityLevel;
//constructor
public Member(T id, T complexityLevel, Class<T> type) {
id = id;
this.complexityLevel = complexityLevel;
this.type = type;
}
Затем позже:
Member<String> mString = new Member<String>("id1", "High", String.class);
...
System.out.println(mString.type.getName());
В качестве альтернативы, если id
гарантируется, что этого никогда не будет null
, вы можете использовать отражение для извлечения Class
объекта, представляющего его тип:
System.out.println(mString.getId().getClass().getName());
Конечно, getClass() вернет a Class<? extends T>
. Итак, если id
на самом деле является подклассом T
, вы получите имя этого класса, а не имя T
.
Комментарии:
1. @neal_fazio — Вы спрашиваете, как получить просто «строку», «Целое число» и т.д.? Вы можете использовать
getSimpleName()
вместоgetName()
.
Ответ №2:
Эта информация (общий тип T) удаляется во время компиляции (стирание типа).
Использование токенов супертипа — это умеренно болезненный метод, который может быть применен здесь. Примером этого является TypeLiteral от Guice.
Кроме того, String и Integer не являются примитивными типами. «int» — это примитив.