简体   繁体   中英

java: Passing Classes as arguments for dependency injection

I was looking at a relatively simple block of code that hit the database and returned the results as a LinkedList. It seemed obvious that the SQL should be injected but then it occurred to me that the LinkedList was an unnecessary dependency too.

The simplified version is as follows:

public List<String> getStrings() {
    //Hard coded reference to LinkedList
    List<String> tmp = new LinkedList<String>();
    tmp.add("foo");
    return tmp;
}

I tried to rewrite it to let me specify the List implementation at runtime.

Calling getStrings(Class< List > listType) with getStrings(LinkedList.class) gives an error about the method not being applicable. The following works ok:

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

However all the references to List and tmp complain about type safety because it really should be List< String >.

Adding the generic works ok at getStrings():

public List<String> getStrings(Class<? extends List<String>> listType) throws InstantiationException, IllegalAccessException {
    List<String> tmp = listType.newInstance();
    tmp.add("foo");
    return tmp;
}

but the updated call doesn't compile at all:

getStrings(LinkedList<String>.class);

The following works, but gives me an unchecked cast warning:

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

Is there a Right Way(tm) to do this?

As you've discovered, runtime reflection doesn't mix well with compile-time generics. If you're using Java 8, I would suggest a much cleaner and safer approach:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM