从泛型类型 T 中获取“类”对象

Posted

技术标签:

【中文标题】从泛型类型 T 中获取“类”对象【英文标题】:Get "Class" object from generic type T 【发布时间】:2021-09-26 06:18:35 【问题描述】:

我想创建返回 XML 文档的对象表示的通用函数(使用 JAXB)。我需要将“类”对象传递给 JAXBContext 构造函数,但是如何从 T 中获取它?

public <T> readXmlToObject(String xmlFileName, T  jaxbClass) 
   JAXBContext context = JAXBContext.newInstance(T.class); // T.class - here error, how to get it?
   .......

【问题讨论】:

搜索“类型擦除”:-) 【参考方案1】:

改为传递类对象,这很容易。

public <T> T readXmlToObject(String xmlFileName, Class<T>  jaxbClass) 
       JAXBContext context = JAXBContext.newInstance( jaxbClass ); // T.class - here error, how to get it?
       Object o = context.createUnmarshaller().unmarshal( new File( xmlFileName ) );
       return jaxbClass.cast( o );

这里的想法是,由于您无法从对象中提取类型参数,因此您必须反其道而行之:从类开始,然后操作对象以匹配类型参数。

【讨论】:

(我不认为? extends 在这里给你买任何东西。)【参考方案2】:

别听别人的……你懂的。

只需将jaxbClass参数的类型改为Class&lt;T&gt;即可:

public <T> T readXmlToObject(String xmlFileName, Class<T> jaxbClass) 
   JAXBContext context = JAXBContext.newInstance(jaxbClass);
   .......

【讨论】:

【参考方案3】:

您无法在运行时获取类。 Java 使用类型安全擦除来实现泛型,这意味着对泛型类型的理解仅适用于编译。如果你想获得它的类,你必须在运行时询问实际的对象。

【讨论】:

-1 错了!正在传入该类。问题在于方法签名 感谢您的意见。正如所写的那样,它不起作用,但我明白你的意思是将输入更改为 Class 而不是 T。那很好。不过,如果因为 Java 的泛型 impl 不好而无需担心,那就太好了。【参考方案4】:

尝试传递类本身,像这样

public <T> readXmlToObject(String xmlFileName, Class<T> class) 

【讨论】:

【参考方案5】:

看看this SO answer。

基本上,类型 T 在运行时不可用 - Java 泛型受制于 erasure by the compiler。

幸运的是,您已经有一个类的实例,因此您可以从那里获取类型信息:

public <T> readXmlToObject(String xmlFileName, T jaxbClass) 

   // if jaxbClass is an instance of the data object, you can do this: 
   JAXBContext context = JAXBContext.newInstance(jaxbClass.getClass());

   // alternatively if jaxbClass is an instance of the Class object: 
   JAXBContext context = JAXBContext.newInstance(jaxbClass);
   // ......

【讨论】:

-1 完全行不通。 jaxbClass.getClass() 将返回 Class.class。你也错了 - 在这里擦除不是问题,因为正在传递类。 啊 - 我假设因为它被限制为 T 而不是 Class 它是类的一个实例(如果你明白我的意思......) 我明白你,但认为这是他的问题 - 他为参数编码了错误的类型。他没有传入T,因为在调用之前他不会有T 的实例,但他可以传入Class&lt;T&gt; 的实例。我承认我将使用参数名称jaxbClass,这非常强烈地表明它是class 我不赞成这一点 - 你的回答并没有如此错,值得反对:)【参考方案6】:
public class XYZ<T> 
    ...
    private Class<T> tClass;    
    ...
    public <T> readXmlToObject(String xmlFileName) 
       JAXBContext context = JAXBContext.newInstance(tClass);
       ...
    
    ...
 

【讨论】:

我认为这行不通,因为 tClass 未初始化,您最终将 null 传递给“JAXBContext.newInstance(..)”调用。 在我的代码中我是这样做的:private Class entityClass; final ParameterizedType type = (ParameterizedType)getClass().getGenericSuperclass(); entityClass = (Class)type.getActualTypeArguments()[0];

以上是关于从泛型类型 T 中获取“类”对象的主要内容,如果未能解决你的问题,请参考以下文章

如何从泛型类访问静态变量?

C#关于反射创建泛型类

如何获取和使用从泛型推断的类型

Kotlin泛型 ① ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 )

从泛型类型快速实例化

如何在打字稿的泛型类中创建类型为“T”的新对象?