-1

如何在超类构造函数中获取泛型类型的类?

换句话说,我想要一个Class<T>实例,其中 T 是我的超类的泛型。这将在下面的代码中用于ChildA我直接在类本身中定义泛型类的类,但是当子类是泛型类时,我也需要它来工作,例如GenericChildB.

     /**
     * empty class
     */
    private static class Foo{}
    
    /**
     * non generic class that extends from a generic class
     */
    private static class ChildA extends GenericClass<Foo>{}
    /**
     * generic class that extends from a generic class
     */
    private static class ClassChildB<T> extends GenericClass<T>{}
    
    private abstract static class GenericClass<T> {
        
        @SuppressWarnings("unchecked")
        public GenericClass() {
            Type type = getClass().getGenericSuperclass();
            /**
             * When constructed from ChildA:
             *      type = generics.Main$GenericClass<generics.Main$Foo>
             *      with other worlds the generic type
             * 
             * But when constructed from GenericChildB:
             *      the generic type is just:
             *      type = generics.Main$GenericClass<T>
             *      and it throws an error when trying to cast his to an ParameterizedType
             *      because <T> is not an acctual class.
             * 
             */
            System.out.println(type);
            Class<T> classInstance = (Class<T>) ((ParameterizedType)type).getActualTypeArguments()[0];
            
            //Goal is to get an Class<T> object inside of the constructor of GenericClass
            System.out.println(classInstance);
        }
    }

    public static void main(String[] args) {
        
        //works : 
        GenericClass<Foo> genericClassA = new ChildA();
        
        //does not work:
        GenericClass<Foo> genericClassB = new GenericChildB<Foo>();
        
    }
4

1 回答 1

1

发生这种情况是因为 Java 中的类型擦除。

在第一种情况下,您在编译时将非泛型类ChildAGenericClassie的具体实现绑定。GenericClass<Foo>所以 Java 能够使用这些信息。

在第二种情况下,和之间的绑定GenericChildBFoo发生在运行时。Java 无法使用此信息。

以这种方式扩展您的示例:

private static class ClassChildC extends ClassChildB<Foo>{}

因为这个类是非泛型的,所以绑定发生在编译时。您将能够再次获得类型信息。

这在您的实际场景中可能可以接受,也可能不可接受,但这几乎是使用 Java 类型擦除保留类型信息的唯一方法。

于 2020-09-26T22:03:59.427 回答