Lester
Lester

Reputation: 1870

How to dynamically assign a certain generic type to a List?

The question title feels quite clumsy. I am grateful for an edit.
I am trying to create a reusable query to return a List of objects of a certain kind that is specified by an assigned String.
This won't work but I suppose it will make clear what I am trying to do:

public List<?> getAll(String type) {
    Class clazz = Class.forName(type);
    return (List<clazz>) em.createQuery("SELECT t from " + type + " t").getResultList();
}

Upvotes: 0

Views: 172

Answers (1)

Thomas
Thomas

Reputation: 88707

Try using the type's class:

public <T> List<T> getAll(Class<T> type) {
  return em.createQuery("SELECT t from " + type.getSimpleName() + " t").getResultList();
}

Note that this will still generate a warning, since getResultList() returns a raw list.

Edit:

If you only have a fully qualified class name, i.e. you need to call Class.forName(), there's no way to know the class at compile time - and since generics (almost) are a compile time feature only (hint: type erasure) they won't help in that case.

You could still call the generic method with a class retrieved by Class.forName() like this:

List<?> l = getAll( Class.forName( typeName ));

You might also not need to get the class object itself, if it is just for the query (however, it might make sense to first check that the string is the name of an existing class). In this case your method might look like this:

public List<?> getAll(String type) {
   return em.createQuery("SELECT t from " + type + " t").getResultList();
}

This variant would also allow you to either pass in a fully qualified class name or an entity name, i.e. it would be somewhat more flexible.

Alternatively you could return List<Object>, which would allow you to add further objects to the list (but beware, you could add anything).

That being said, I'd use the first option whenever possible and the second option as a fallback when the concrete type (or at least some interface) is unknown at compile time.

Upvotes: 5

Related Questions