我正在查看一个相对简单的代码块,该代码块命中数据库并将结果作为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);
}

09-08 07:46