Skip to main content
 首页 » 编程设计

java之在运行时获取类的泛型类型不起作用

2024年06月03日27三少

我有两个类和一个接口(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; 
    } 
 
} 

我已经尝试了所有可能的方法来获取通用类型的类。我关注了Get generic type of class at runtime 甚至尝试了该页面中给出的所有解决方案。但仍然没有得到任何运气。

即使有 Gauva

https://stackoverflow.com/a/19775924/2290078 获取 getType() 的输出不是实际的泛型类

我的测试代码是

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

请您参考如下方法:

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

这样你就找到了here无法检索通用:

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

因为它静态地检索Reader 的直接父类(super class)中定义的参数化类型,在本例中为Object

在子类构造函数中移动此代码也不会起作用:

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

因为它静态地检索Reader 类中定义的参数化类型,即T。由于 T 没有任何绑定(bind),您仍然会得到 Object 类作为返回类。

您的情况适用哪种解决方案?

泛型在编译后被删除。所以要知道运行时使用的参数化类型信息是Test here :

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

您必须在您的实际代码中显式“传递”代表泛型的 Class
为此,在构造函数中添加一个代表泛型类型的 Class 参数并将其存储在一个字段中。现在您有一种在运行时引用类型的方法。

public class ExcelReader<T> extends Reader<T> implements RowColumnReader<T> { 
 
   private Class<T> genericType; 
 
   public ExcelReader(Class<T> genericType){ 
       this.genericType = genericType; 
   } 
   /*...*/ 
} 

现在您可以用这种方式实例化 ExcelReader:

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