我正在查看一个相对简单的代码块,该代码块命中数据库并将结果作为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&lt; List&gt; 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&lt;字符串&gt;。
在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);
有没有正确的方法(tm)呢?
答案 0 :(得分:2)
正如您所发现的,运行时反射与编译时泛型不能很好地混合。如果您正在使用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);
}