泛型 - 获取引用类型
Generics - Get the reference type
我在获取列表类型时遇到问题。问题是在声明时我没有指定类型。我只在 运行 时间设置它。
我有一个 POJO class
public class MyObject<T> {
private String name;
private List<T> list;
//getter and setter
}
我已关注 this SO question 并尝试了以下代码
public class ListType {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
ListType listType = new ListType();
List<Integer> listInt = new ArrayList<Integer>();
MyObject<Integer> myObjectInt = new MyObject<Integer>();
myObjectInt.setList(listInt);
listType.initialize(myObjectInt);
MyObject<String> myObjectStr = new MyObject<String>();
List<String> listStr = new ArrayList<String>();
myObjectStr.setList(listStr);
listType.initialize(myObjectStr);
}
private void initialize(MyObject myObject) throws NoSuchFieldException, SecurityException {
List list = myObject.getList();
ListType listType = new ListType();
listType.getListType(list);
}
private void getListType(List list) throws NoSuchFieldException, SecurityException {
Field stringListField = MyObject.class.getDeclaredField("list");
ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType();
Class<?> stringListClass = (Class<?>) stringListType.getActualTypeArguments()[0];
System.out.println(stringListClass);
}
}
然后我得到以下异常
Exception in thread "main" java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
at com.sample.listtype.ListType.getListType(ListType.java:35)
at com.sample.listtype.ListType.initialize(ListType.java:27)
at com.sample.listtype.ListType.main(ListType.java:15)
如果我设置在 运行 时间,如何获取类型?
这个方法getGenericType()
has the return type Type
which, amongst others, can be Class
or ParameterizedType
. It makes sense to me that it wouldn't return ParameterizedType
if invoked on a field which has no parameterized type. It seems to return Class
in this case. The javadoc有点不确定。
关于如何在运行时获取实际类型的问题:通用类型信息在运行时被删除。它仅用于确保编译时的类型安全。当你将一个实际类型ArrayList<Integer>
的对象赋值给一个静态类型List
的变量时,你无法在运行时得到实际对象的泛型类型。您可以做的是检查列表中包含的对象的类型:
Class<?> foo = list.get(0).getClass();
我不认为你想要实现的是可能的。然而,对代码稍作改动就可以解决问题:
public class MyObject {
private List<?> list;
private Class<?> type;
public <T> void setList(List<T> list, Class<T> c) {
this.list = list;
this.type = c;
}
public List<?> getList() {
return list;
}
public Class<?> getType() {
return type;
}
}
示例代码:
public static void main(String[] args) throws NoSuchFieldException,
SecurityException {
List<Integer> list = new ArrayList<Integer>();
MyObject myObject = new MyObject();
myObject.setList(list, Integer.class);
System.out.println(myObject.getType());
}
输出:
class java.lang.Integer
我在获取列表类型时遇到问题。问题是在声明时我没有指定类型。我只在 运行 时间设置它。
我有一个 POJO class
public class MyObject<T> {
private String name;
private List<T> list;
//getter and setter
}
我已关注 this SO question 并尝试了以下代码
public class ListType {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
ListType listType = new ListType();
List<Integer> listInt = new ArrayList<Integer>();
MyObject<Integer> myObjectInt = new MyObject<Integer>();
myObjectInt.setList(listInt);
listType.initialize(myObjectInt);
MyObject<String> myObjectStr = new MyObject<String>();
List<String> listStr = new ArrayList<String>();
myObjectStr.setList(listStr);
listType.initialize(myObjectStr);
}
private void initialize(MyObject myObject) throws NoSuchFieldException, SecurityException {
List list = myObject.getList();
ListType listType = new ListType();
listType.getListType(list);
}
private void getListType(List list) throws NoSuchFieldException, SecurityException {
Field stringListField = MyObject.class.getDeclaredField("list");
ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType();
Class<?> stringListClass = (Class<?>) stringListType.getActualTypeArguments()[0];
System.out.println(stringListClass);
}
}
然后我得到以下异常
Exception in thread "main" java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
at com.sample.listtype.ListType.getListType(ListType.java:35)
at com.sample.listtype.ListType.initialize(ListType.java:27)
at com.sample.listtype.ListType.main(ListType.java:15)
如果我设置在 运行 时间,如何获取类型?
这个方法getGenericType()
has the return type Type
which, amongst others, can be Class
or ParameterizedType
. It makes sense to me that it wouldn't return ParameterizedType
if invoked on a field which has no parameterized type. It seems to return Class
in this case. The javadoc有点不确定。
关于如何在运行时获取实际类型的问题:通用类型信息在运行时被删除。它仅用于确保编译时的类型安全。当你将一个实际类型ArrayList<Integer>
的对象赋值给一个静态类型List
的变量时,你无法在运行时得到实际对象的泛型类型。您可以做的是检查列表中包含的对象的类型:
Class<?> foo = list.get(0).getClass();
我不认为你想要实现的是可能的。然而,对代码稍作改动就可以解决问题:
public class MyObject {
private List<?> list;
private Class<?> type;
public <T> void setList(List<T> list, Class<T> c) {
this.list = list;
this.type = c;
}
public List<?> getList() {
return list;
}
public Class<?> getType() {
return type;
}
}
示例代码:
public static void main(String[] args) throws NoSuchFieldException,
SecurityException {
List<Integer> list = new ArrayList<Integer>();
MyObject myObject = new MyObject();
myObject.setList(list, Integer.class);
System.out.println(myObject.getType());
}
输出:
class java.lang.Integer