泛型方法中需要Java冗余强制转换
我正在寻找一种方法,用泛型函数优化代码库中的某些内容。有一个返回类型为List<Object>
的函数,其返回类型可能为List<SpecifiedType>
Bellow是该函数的最简版本,称为function
。它采用一个参数类型,基于它调用相应的函数(这里限制为String
)或泛型函数
public static ArrayList<String> forString(){
ArrayList<String> res = new ArrayList<>();
// Fetching and processing data specific to String
return res;
}
public static <T> ArrayList<T> forGeneric(Class<T> type){
ArrayList<T> res = new ArrayList<>();
// Fetching data
return res;
}
public static <T> ArrayList<T> function(Class<T> type){
if(type == String.class)
return (ArrayList<T>) forString();
return forGeneric(type);
}
目标是像这样调用上面的函数:ArrayList<SomeType> someTypes = function(SomeType.class);
关于上述代码,我注意到两件事:
强制转换到
ArrayList<T>
是必需的,即使我们知道如果将类型String
作为参数传递,它将返回ArrayList<String>
,就像forString()
方法一样强制转换为
ArrayList<T>
会给出Unchecked cast
警告,即使返回类型为ArrayList<String>
我的问题是,有没有更好的方法来做到这一点(最好不用演员阵容),如果没有,为什么
# 1 楼答案
运行时代码无法基于运行时信息返回不同的泛型类型,因为泛型是一种编译时机制
为了避免编译器警告,我将返回一个新列表:
这可能看起来很浪费,但事实并非如此。新列表不是新对象的列表,只是新引用。一个引用非常小,可能不超过256字节,所以一个包含4000个对象的列表所占用的内存不会超过1兆字节
# 2 楼答案
首先,这种说法在逻辑上是错误的
如果
type
是Class<String>
,那么isInstance
正在检查参数是否是字符串实例。您传递的参数是一个类实例(具体地说,是一个Class<String>
)如果你愿意
你的意思是
然而,即使解决了这个逻辑错误,代码仍然会有一个未经检查的强制转换警告
你错过的部分就在这里
没错我们知道这一点。但是我们知道的和编译器知道的是两件不同的事情。编译器不够聪明,无法检查条件并意识到类型是正确的。它可以想象足够聪明,但事实并非如此
这正是为什么这表现为警告而不是错误。这是一个警告,因为你所做的事可能是错误的;它肯定不是错的,否则它根本不会编译。在这种情况下,警告应该作为一个提示,让你再次检查你所做的是正确的,然后你可以愉快地抑制它
最后,它可能是你精心设计的例子的产物,但所有这些方法都是无用的。与直接调用
new ArrayList<>()
相比,似乎没有任何优势。在运行时,实际实例是相同的,无论它来自3种方法中的哪一种