【问题标题】:How can I pass a generic class to a method in Java?如何将泛型类传递给 Java 中的方法?
【发布时间】:2011-08-06 17:07:47
【问题描述】:
假设我们有一个函数可以创建给定特定类的对象:
public static <T> T createObject(Class<T> generic) {
try {
return generic.newInstance();
} catch (Exception ex) {
return null;
}
}
我们可以轻松地使用该函数来创建非泛型类型的实例。
public static void main(String[] args) {
Foo x = createObject(Foo.class);
}
是否可以用泛型类型做同样的事情?
public static void main(String[] args) {
ArrayList<Foo> x = createObject(ArrayList<Foo>.class); // compiler error
}
【问题讨论】:
标签:
java
generics
dynamic
methods
arguments
【解决方案1】:
Java 中的泛型是通过类型擦除实现的。
这意味着ArrayList<T> 在运行时是ArrayList。编译器只是为你插入强制转换。
您可以使用以下方法对此进行测试:
ArrayList<Integer> first = new ArrayList<Integer>();
ArrayList<Float> second = new ArrayList<Float>();
if(first.getClass() == second.getClass())
{
// should step in the if
}
【解决方案2】:
如果你真的需要你可以强制它编译没有错误或警告:
@SuppressWarnings("unchecked")
ArrayList<Foo> x = (ArrayList<Foo>) createObject(ArrayList.class);
唯一的问题是在编译时它不能保证createObject() 不会向你的ArrayList 添加不属于Foo 类型的对象。在您的情况下,这可能是安全的,因此您仍然可以获得泛型的好处,而无需使用ArrayList<?>。
【解决方案3】:
此外,只要您确定自己在做什么,并且只要您非常确定您的代码不会引起堆污染,您就可以抑制警告。
您可能还考虑到您的代码无法实例化数组,这也需要一个未经检查的异常:
@SuppressWarnings("unchecked")
public static <T> T[] createArray(Class<T> anyClass, int size){
T[]result = null;
try{
result = (T[]) Array.newInstance(anyClass, size);
}catch(Exception e){
e.printStackTrace();
}
return result;
}
我是这样使用的:
public static void main(String[] args) throws Exception{
@SuppressWarnings("unchecked")
List<String> jediNames = (List<String>) createObject(ArrayList.class);
jediNames.add("Obiwan");
String[] moreJedis = createArray(String.class, 10);
System.out.println(moreJedis.length);
moreJedis[0] = "Anakin";
}