首页 > 解决方案 > 如何获取 Foo 类型的类实例(富.class 不起作用)

问题描述

我想获得 Foo<T>.class 的类(确切地说是 Foo<T>,既不是 T.class 也不是 Foo.class)

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

在 StackOverflow 上有一条通过注入构造函数来获取泛型类的指令,但这不是我的情况,因为 C<D>.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
      }
    }

标签: java

解决方案


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

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>

推荐阅读