如何检索参数化类

时间:2018-01-12 14:42:49

标签: java generics

请考虑以下代码:

public class Context {
    private final Class<?> clazz;
    private final String resource;
    private final com.thirdparty.Context context;

    public Context(final String resource, final Class<?> clazz) {
        this.clazz = clazz;
        this.resource = resource;
        this.context = com.thirdparty.Context.newInstance(this.clazz);
    }

    public String marshall(final Object element) {
        return this.context.marshall(element);
    }

    public Object unmarshall(final String element) {
        return this.context.unmarshall(element);
    }
}
Context context = new Context("request.xsd", Request.class);

// Marshall
Request request = new Request();
String xml = context.marshall(request);

// Unmarshall
Request roundTrip = Request.cast(context.unmarshall(xml));

我试图将它替换为Context类的泛型版本:

public class Context<T> {
    private final Class<T> clazz;
    private final String resource;
    private final com.thirdparty.Context context;

    public Context(final String resource) {
        this.clazz = initHere(); // <== HOW ??
        this.resource = resource;
        this.context = com.thirdparty.Context.newInstance(this.clazz);
    }

    public String marshall(final T element) {
        return this.context.marshall(element);
    }

    public T unmarshall(final String element) {
        return this.clazz.cast(this.context.unmarshall(element));
    }
}
Context<Request> context = new Context<>("request.xsd");

// Marshall
Request request = new Request();
String xml = context.marshall(request);

// Unmarshall
Request roundTrip = context.unmarshall(xml);

因此,我不会将.class作为参数传递给构造函数,而unmarshall方法会自动转换返回对象。

我需要知道传递给newInstance()方法的T类,并调用cast()方法。即T.class或T.getClass()。

在我的例子中,我试图在构造函数中初始化clazz成员,以便我可以在两个位置使用它。

我尝试了以下内容:

this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

但是getClass()。getGenericSuperclass()返回一个无法强制转换为ParameterizedType的对象。我不能使用任何第三方反射库,我需要坚持Jdk内部的标准机制。

3 个答案:

答案 0 :(得分:4)

你不能这样做。 在您的情况下,通用类型T链接到您的实例。反射数据绑定到Class,而您的类不定义类型T.

您尝试使用的代码仅在您定义了设置T的类时才有效。

public class RequestContext extends Context<Request> {}

如果您使用此类的实例,那么您的代码应该可以正常工作。

答案 1 :(得分:3)

您无法在构造函数中执行此操作。如果你没有将Class实例传递给构造函数,那么Context类就无法处理它所处理的对象。

看看这里: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html#Reflection

要确定类型和泛型类型,您需要一个对象。而且你没有物体。

是否有特定原因可以将Class参数添加到构造函数中?如果有,你的例子并没有说清楚。

答案 2 :(得分:1)

实际上,您非常接近实际的解决方案......您的第一个代码版本非常接近您的需求:

自:

public Context(final String resource, final Class<?> clazz) {
        //...
}

要:

public Context(final String resource, final Class<T> clazz) {
       // ...
}

单个?T更改就可以了。