Search code examples
javagenericsreflectiontype-erasure

Generic type of local variable at runtime


Is there a way in Java to reflect a generic type of a local variable? I know you can do that with a field - Get generic type of java.util.List. Any idea how to solve, for instance:

public void foo(List<String> s){
  //reflect s somehow to get String
}

Or even more general:

public void foo<T>(List<T> s){
  //reflect s somehow to get T
}

Solution

  • Here is nice tutorial that shows how and when you can read generic types using reflection. For example to get String from your firs foo method

    public void foo(List<String> s) {
        // ..
    }
    

    you can use this code

    class MyClass {
    
        public static void foo(List<String> s) {
            // ..
        }
    
        public static void main(String[] args) throws Exception {
            Method method = MyClass.class.getMethod("foo", List.class);
    
            Type[] genericParameterTypes = method.getGenericParameterTypes();
    
            for (Type genericParameterType : genericParameterTypes) {
                if (genericParameterType instanceof ParameterizedType) {
                    ParameterizedType aType = (ParameterizedType) genericParameterType;
                    Type[] parameterArgTypes = aType.getActualTypeArguments();
                    for (Type parameterArgType : parameterArgTypes) {
                        Class parameterArgClass = (Class) parameterArgType;
                        System.out.println("parameterArgClass = "
                                + parameterArgClass);
                    }
                }
            }
        }
    }
    

    Output: parameterArgClass = class java.lang.String

    It was possible because your explicitly declared in source code that List can contains only Strings. However in case

    public <T> void foo2(List<T> s){
          //reflect s somehow to get T
    }
    

    T can be anything so because of type erasure it is impossible to retrieve info about precise T class.