如何获取类型为Foo <t>的类实例(Foo <t> .class不起作用)

时间:2018-07-29 07:49:39

标签: java

我想获取Foo .class的类(正是Foo ,既不是T.class也不是Foo.class)

public class A extends B<C<D>>{
   public A() {
     super(C<D>.class); // not work
   }
}

在StackOverflow上有一条指令,说明如何通过注入构造函数来获取通用类,但这不是我的情况,因为C .class(例如List < String> .class)是语法错误。在这里,与语法有关的不仅仅是代码结构。

为显示更多详细信息,更高级的视图,原始代码如下,即Spring框架中的HATEOAS模块:

public class CustomerGroupResourceAssembler extends ResourceAssemblerSupport<CustomerGroup, CustomerGroupResource>{
   public CustomerGroupResourceAssembler() {
      super(CustomerGroupController.class, CustomerGroupResource.class);
   }
}
public class CustomerGroupResource extends ResourceSupport {
   private CustomerGroup data;
}

但是现在我想将CustomerGroupResource参数化为

public class Resource<T> extends ResourceSupport {
   private T data;
}

然后

    public class CustomerGroupResourceAssembler extends ResourceAssemblerSupport<CustomerGroup, Resource<CustomerGroup>>{
      public CustomerGroupResourceAssembler() {
         super(CustomerGroupController.class, Resource<CustomerGroup>.class); // not work here, even Resource.class
      }
    }

2 个答案:

答案 0 :(得分:0)

很遗憾,由于类型擦除,您要尝试执行的操作是不可能的。

有关泛型类型的信息仅在编译时提供,而在运行时不提供。这是在Java中使用泛型的最大限制之一。这样做的原因是为了保持向后兼容性。

请参见Java generics type erasure: when and what happens?

答案 1 :(得分:0)

由于类型擦除,泛型仅在编译时适用,对运行时没有任何意义。你能做的就是

public class A extends B<C<D>>{
   public A() {
     super((Class<C<D>>) C.class);
   }
}

但是,您将无法在运行时确定D的类型。您可以使用反射来获取超级类型。

public class Main {
    public static abstract class B<X> {
        protected B() {
            Type type = getClass().getGenericSuperclass();
            System.out.println(type);
        }
    }

    public static class A extends B<Supplier<String>> {
        public A() {
        }
    }

    public static void main(String[] args) {
        new A();
    }
}

打印

Main.Main$B<java.util.function.Supplier<java.lang.String>>

编辑您的具体示例即可。

import java.lang.reflect.Type;

public interface Main {

    class ResourceSupport {

    }

    class CustomerGroup {

    }

    public class Resource<T> extends ResourceSupport {
        private T data;
    }

    abstract class ResourceAssemblerSupport<C, R> {
        protected ResourceAssemblerSupport() {
            Type type = getClass().getGenericSuperclass();
            System.out.println(type);

        ParameterizedType pt = (ParameterizedType) type;
        Type[] actualTypeArguments = pt.getActualTypeArguments();
        Class first = (Class) actualTypeArguments[0];
        ParameterizedType second = (ParameterizedType) actualTypeArguments[1];

        System.out.println(pt.getRawType() + " <" + first + ", " + second + ">");
        }
    }

    public class CustomerGroupResourceAssembler extends ResourceAssemblerSupport<CustomerGroup, Resource<CustomerGroup>>{
        public CustomerGroupResourceAssembler() {
        }
    }

    public static void main(String[] args) {
        new CustomerGroupResourceAssembler();
    }
}

打印

Main.Main$ResourceAssemblerSupport<Main$CustomerGroup, Main.Main$Resource<Main$CustomerGroup>>
class Main$ResourceAssemblerSupport <class Main$CustomerGroup, Main.Main$Resource<Main$CustomerGroup>>

一种执行所需功能的通用方法是使用辅助函数,但是我认为您不需要这样做。

public static void main(String[] args) {
    System.out.println(new ClassType<List<String>>() {}.getType());
}

interface ClassType<T> {
    default Type getType() {
        ParameterizedType type = (ParameterizedType) getClass().getGenericInterfaces()[0];
        return type.getActualTypeArguments()[0];
    }
}

打印

java.util.List<java.lang.String>