简体   繁体   中英

Get generic type of class at runtime is not working

I have two classes and one interface

public class ExcelReader<T> extends Reader<T> implements RowColumnReader<T> {

    // private final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {};
    // private final Type type = typeToken.getType(); 
    /* public Type getType() {
        return type;
        }*/
    // Useing Guava getting System.out.println(reader.getType()) T as ouput

        @Override
        public List<T> readFile(String file) {
          //my code
        }
    }
public abstract class Reader<T> {
    protected Class<T> clazz;

    /*public Reader() {
        clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }*/
    // Constructor is commented beacuse getting Exception java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
}

public interface RowColumnReader<T> extends HeaderFields<T>{

    public List<T> readFile(String file);
}

public interface HeaderFields<T> {

    default List<String> getHeader(Class<T> clazz) throws HeaderNotDefiendException {
        //my code
        return headerList;
    }

}

I have tried all possible way to get class of generic type. I followed Get generic type of class at runtime and even tried all solution given in that page. But still not getting any luck.

Even with Gauva

https://stackoverflow.com/a/19775924/2290078 getting the output of getType() is T not the actual generic class

My test code is

Reader<Test> reader = new ExcelReader<>();
//System.out.println(reader.getType());  ---> output is T 
List<Test> list = reader.readFile("Sample.xlsx");
System.out.println(list);

It is not just a matter of "What API should I use to get the generic type at runtime?". It depends upon what you want to do with the generic type( T ).

Generics are more of a compile-time checking feature and can impose some useful restrictions using T extends and T super . That's it. This might be useful Difference between <? super T> and <? extends T> in Java

If you want to know the type T at runtime and do condition implementation using something like a switch then the class you are declaring generic is not really generic class by definition as the implementation differs for the different type and hence it is not gracefully supported.

I have tried all possible way to get class of generic type.

This way that you found here is not working to retrieve the generic :

public Reader() {
    clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

because it retrieves statically the parameterized type defined in the immediate superclass of Reader , that in this case is Object .

Moving this code in the subclass constructor will not work either :

public ExcelReader() {
    clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

as it retrieves statically the parameterized type defined in the Reader class, that is T . As T doesn't have any bound, you will still get the Object class as returned class.

Which solution to apply in your case ?

Generics are erased after compilation. So to be aware that the parameterized type information used at runtime is Test here :

Reader<Test> reader = new ExcelReader<>();

you have to explicitly "pass" the Class representing the generic in your actual code.
To do that, add in the constructor a Class parameter representing the generic type and store it in a field. Now you have a way to refer the type at runtime.

public class ExcelReader<T> extends Reader<T> implements RowColumnReader<T> {

   private Class<T> genericType;

   public ExcelReader(Class<T> genericType){
       this.genericType = genericType;
   }
   /*...*/
}

Now you can instantiate ExcelReader in this way :

ExcelReader<Test> excelReader = new ExcelReader<>(Test.class);

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