2016-12-15 35 views
0

我正在查看一个相对简单的代码块,它碰到数据库并将结果作为LinkedList返回。似乎很明显,SQL应该被注入,但后来我想到LinkedList也是不必要的依赖。java:传递类作为依赖注入的参数

的简化版本如下:

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(类< List> 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); 
} 

但是所有引用到列表和TMP抱怨类型安全,因为它真的应该名单< String>终止。

在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); 

下工作,但给了我一个unchecked投警告:

getStrings((Class<? extends List<String>>) LinkedList.class); 

是否有一个正确的方式(TM)来做到这一点?

回答

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); 
}