如何在Java中做“MyClass<String>.class”?

2022-09-03 13:24:04

如何使用clazz调用,我不能实例化或扩展MyClass。public <T> T doit(Class<T> clazz);MyClass<String>.class

编辑:“David Winslow”和“bmargulies”的回答是原始问题的正确作品,但令人惊讶的是,当方法返回时,说而不是铸造将不再编译。(MyClass<String>) doit(MyClass.class);MyClass<T>T

编辑:我已将列表替换为MyClass,并将条件添加到我的原始问题中。


答案 1

用。由于类型擦除,Java类的类型参数完全是编译时构造 - 即使语法有效,它也将与 等完全相同的类。由于反射本质上是运行时的事情,因此它不能很好地处理类型参数(如在Java中实现的那样)。List.classList<String>.classList<Date>.class

如果要使用 Class 对象(例如)实例化新的 List 实例,则可以将该操作的结果强制转换为具有适当的类型参数。

List<String> list = (List<String>)(ArrayList.class.newInstance());

答案 2

我见过类似的问题被问过几次,例如获取泛型类类型

构造静态泛型类型有正当理由。在op'的情况下,他可能希望

MyClass<String> result = doit(MyClass<String>.class);

如果没有语言语法支持,强制转换是正确的方法。如果经常需要这样做,则应将铸造放入一种方法中,例如

public class MyClass<T>
{
    @SuppressWarnings("unchecked")
    // may need a better method name
    static public <T2> Class<MyClass<T2>> of(Class<T2> tClass)
    {
        return (Class<MyClass<T2>>)(Class<?>)(MyClass.class);
    }
}

MyClass<String> result = doit(MyClass.of(String.class)); // no warning

在确保演员安全后,我们可以单独压制该方法的警告。任何呼叫站点都不会看到警告。

这都是编译时选角游戏。在运行时,所有类型参数都被擦除,实际上只有裸类对象被传递。该方法很可能会优化,因此对于JVM,最后一行只不过是of

MyClass result = doit(MyClass.class)

有时,在运行时,我们需要一个完整的类型。需要获取一个对象来表示 。MyClass<String>ParameterizedTypeMyClass<String>

当这两个要求组合在一起时,也就是说,我们需要一个编译时表达式,它将在运行时计算为MyClassStringParameterizedType

ParameterizedType type_MyClass_String = ???? MyClass ?? String ???

有一种技术涉及一个匿名子类MyClass<String>

ParameterizedType type_MyClass_String = superTypeOf( new MyClass<String>(){} );

我觉得这很令人不安。


推荐