我正在查看一个相对简单的代码块,该代码块命中数据库并将结果作为LinkedList返回。显然应该注入SQL,但后来我发现LinkedList也是不必要的依赖项。
简化版如下:
public List<String> getStrings() {
//Hard coded reference to LinkedList
List<String> tmp = new LinkedList<String>();
tmp.add("foo");
return tmp;
}
我试图重写它,以便在运行时指定List实现。
使用getStrings(LinkedList.class)调用getStrings(Class listType)会给出有关该方法不适用的错误。以下工作正常:
public List getStrings(Class<? extends List> listType) throws InstantiationException, IllegalAccessException {
List tmp = listType.newInstance();
tmp.add("foo");
return tmp;
}
public void caller() throws InstantiationException, IllegalAccessException {
List stringList = getStrings(LinkedList.class);
}
但是,所有对List和tmp的引用都抱怨类型安全,因为它实际上应该是List 。
在getStrings()中可以正常添加泛型工作:
public List<String> getStrings(Class<? extends List<String>> listType) throws InstantiationException, IllegalAccessException {
List<String> tmp = listType.newInstance();
tmp.add("foo");
return tmp;
}
但更新后的调用根本无法编译:
getStrings(LinkedList<String>.class);
以下工作有效,但给了我未经检查的强制转换警告:
getStrings((Class<? extends List<String>>) LinkedList.class);
有没有正确的方法来做到这一点?
最佳答案
如您所知,运行时反射与编译时泛型不能很好地混合。如果您使用的是Java 8,我建议您使用一种更清洁,更安全的方法:
public List<String> getStrings(Supplier<List<String>> listSupplier) {
List<String> tmp = listSupplier.get();
tmp.add("foo");
return tmp;
}
public void caller() {
List<String> stringList = getStrings(LinkedList::new);
}