如何用泛型在java中实例化类实例?
我正在尝试从XML文件中读取数据,然后实例化一个对象,以便将该对象的其他属性(从XML文件读取)添加到该对象中。我认为最简单的方法(这样我就不必读取类方法名称并找到setter)是用构造函数中的所有值实例化对象。
我正在尝试这样做,所以我需要这样的东西:T obj = new Object()
,但要获得对象类
private static final boolean string_field = true;
private static <T> T getObject(Element e, String[] fieldNames, boolean[] fieldTypes) {
Object[] values = new Object[fieldNames.length];
for (int i=0; i<fieldNames.length; i++) {
values[i] = (fieldTypes[i]==string_field)? getStringValue(e, fieldNames[i])
: getIntegerValue(e, fieldNames[i]);
}
return new T(values);
}
谢谢你的建议。
编辑:
这是我更新的代码(未经测试):
public static <T> List<T> populateObjectList(Document xmlDoc, String tagName,
Class clazz, String[] fieldNames, Class[] fieldTypes) {
List<T> objList = new ArrayList<T>();
NodeList nl = xmlDoc.getElementsByTagName(tagName);
if (nl!=null && nl.getLength()>0) {
for (int i=0; i<nl.getLength(); i++) {
Element e = (Element) nl.item(i);
T t;
try {
t = getObject(e, clazz, fieldNames, fieldTypes);
objList.add(t);
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (IllegalArgumentException ex) {
} catch (InvocationTargetException ex) {
} catch (NoSuchMethodException ex) {
}
}
}
return objList;
}
private static <T> T getObject(Element e, Class clazz, String[] fieldNames, Class[] fieldTypes)
throws InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException {
Object[] initargs = new Object[fieldNames.length];
for (int i=0; i<fieldNames.length; i++) {
initargs[i] = (fieldTypes[i].getName().equals("int"))?
getIntegerValue(e, fieldNames[i])
: getStringValue(e, fieldNames[i]);
}
return (T) clazz.getConstructor(fieldTypes).newInstance(initargs);
}
我发布这个是为了让你们中的一些人理解我想做什么。
再次感谢大家的建议。
不能实例化泛型类型。Java泛型有一个令人讨厌的特性,称为类型擦除,这基本上意味着JVM不知道在运行时泛型类或方法使用了什么类型。这是为了与泛型类的前泛型版本(如集合)向后兼容。
您可以做的是将Class<T> clazz
添加到您的参数列表中,然后将方法的末尾替换为:
Class<?>[] paramTypes = new Class[values.length];
for (int i = 0; i < paramTypes.length; i++) {
paramTypes[i] = values[i].getClass();
}
return clazz.getConstructor(paramTypes).newInstance(values);
如果类没有按正确顺序采用正确类型和数量的参数的构造函数,则会引发异常。
CAVEAT:只有当构造函数的参数类型与对象类型完全相同时,这才有效。例如,如果values
由{ "Hello", new Integer(2) }
组成,那么它将只找到签名为SomeClass(String, Integer)
的构造函数,而找不到签名为SomeClass(Object, Object)
的构造函数。
您怎么知道T
包含一个接受单个Object[]
参数的构造函数?解决这个问题的方法是通过一个抽象的工厂。
interface ThingFactory { // Choose an appropriate name.
T create(Object[] values);
}
private static <T> T getObject(
ThingFactory<T> factory, Element e, String[] fieldNames, boolean[] fieldTypes
) {
...
return factory.create(values);
}
现在T
可能甚至没有一个相当奇怪的Object[]
构造函数。CCD_ 11可能是一个抽象类型。工厂可能会根据参数返回不同的类型。也许有时这些产品是可以缓存的不可变对象。
您不能执行new T()
,因为在运行时,T
实际上只是Object
。编译器使用泛型进行类型检查(例如,不能将Integer
放入List<String>
),但随后会丢弃泛型信息。所有类型的参数都有一个已编译的方法副本,因此它无法知道您希望它实例化哪种类型。
有关类型擦除的详细信息,请阅读。
我真的看不出你的问题,是不是不可能使用obj.getClass?