Phu Nguyen
Phu Nguyen

Reputation: 451

Get type of generic type inside a List in Java

I have the below function:


    public <T> void putList(String key, List<T> lst){
          if (T instanceof String) {
          // Do something       
          }
          if (T instanceof Integer) {
          // Do something   
          }
    }

Inside this function, i want to know if <T> is String or Integer so i wonder if there is a way to discover its type? I used the above code but it generated error

Thank you in advance.

Upvotes: 7

Views: 17858

Answers (7)

MCS97
MCS97

Reputation: 11

If you want to run function of the object, you can do:

public <T> void putList(String key, List<T> lst){
    for(T object : lst){
         if(object instanceof String) {
             doSomething(((String)object).doForString())
         }
         if(object instanceof Integer) {
             doSomething(((Integer)object).doForInteger())
         }
    }
}

Upvotes: 0

Brad Cupit
Brad Cupit

Reputation: 6580

It's not possible in Java due to erasure. What most people do instead is add a type token. Example:

public <T> void putList(String key, List<T> list, Class<T> listElementType) {
}

There are certain situations where reflection can get at the type parameter, but it's for cases where you've pre-set the type parameter. For example:

public class MyList extends List<String> {
    private List<String> myField;
}

In both of those cases reflection can determine the List is of type String, but reflection can't determine it for your case. You'd have to use a different approach like a type token.

Upvotes: 9

AlexR
AlexR

Reputation: 115338

Generics are called "erasures" because they exist at compile time only and are removed by compiler. So, there is no way to determine the generic type of collection. The only way to do it for non-empty lists is to take the first element and determine its type.

This is almost the same solution that was suggested by DJClayworth, but I think that there is no need to check each element of the list. If you are sure that the list is created with generics (new ArrayList() or new LinkedList() etc) all its element are guaranteed to be of the same type.

Upvotes: 1

DJClayworth
DJClayworth

Reputation: 26856

It is not possible to determine this due to erasure, which means that the parameter is not stored in the code. However you can either pass an extra parameter specifying what type the list is:

public <T> void putList(String key, List<T> lst, Class<T> listElementType) {

}

or you can determine the type of each element at runtime:

public <T> void putList(String key, List<T> lst){
  for (Object elem:lst) {
      if (elem instanceof String) {
      // Do something       
      }
      if (elem instanceof Integer) {
      // Do something   
      }
  }
}

Upvotes: 1

Neil
Neil

Reputation: 5780

Type genericType = lst.getType();

if(genericType instanceof ParameterizedType){
    ParameterizedType aType = (ParameterizedType) genericType;
    Type[] fieldArgTypes = aType.getActualTypeArguments();
    for(Type fieldArgType : fieldArgTypes){
        Class fieldArgClass = (Class) fieldArgType;
        System.out.println("fieldArgClass = " + fieldArgClass);
    }
}

Upvotes: -1

Teja Kantamneni
Teja Kantamneni

Reputation: 17472

You can not find the type of T as the type information is erased. Check this for more details. But if the list is not empty, you can get an element from the list and can find out using instanceof and if else

Upvotes: 9

pauljwilliams
pauljwilliams

Reputation: 19225

Use the instanceof operator.

That said, generic operations should be, well, generic, so be wary of changing behaviour based on type.

Upvotes: -1

Related Questions