假设我们有一个函数可以创建给定特定类的对象:
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
}
答案 0 :(得分:8)
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
}
答案 1 :(得分:1)
此外,只要您确定自己在做什么,并且只要您确信您的代码不会产生堆污染,您就可以取消警告。
您可能还会考虑到您的代码无法实例化数组,这很可能也需要一个未经检查的异常:
@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";
}
答案 2 :(得分:0)
如果你真的需要,你可以强制它编译而不会出现错误或警告:
@SuppressWarnings("unchecked")
ArrayList<Foo> x = (ArrayList<Foo>) createObject(ArrayList.class);
唯一的麻烦是,在编译时,它无法保证createObject()
不会向ArrayList
添加非{1}类型的对象。在您的情况下,这可能是安全的,因此您仍然可以获得仿制药的好处而无需使用Foo
。