如何使用类标记保留嵌套泛型的泛型类型 [英] How to keep generic type of nested generics with class tokens

查看:98
本文介绍了如何使用类标记保留嵌套泛型的泛型类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java中解决类型擦除的标准方法是将类令牌传递到构造函数中.例如,我们可以定义一个通用属性类,如下所示:

The standard way in Java to work around type erasure is to pass a class token into the constructor. For example we could define a generic property class like this:

class Prop<T> {
    public Prop(Class<T> type) {
        this.type = type;
    }
    Class<T> type;
    T t;
}

class IntProp extends Prop<Integer> {
    public IntProp() {
        super(Integer.class);
    }
}

但是如果我现在想使用另一个泛型类型参数(例如列表)并保留其泛型类型该怎么办.我本想这样做的:

But what if I now want to use another generic type argument, such as a list and also keep its generics type. I would have liked to do this:

class ListProp<J> extends Prop<ArrayList<J>> {
    Class<J> subtype;
    public ListProp(Class<J> type) {
        super(ArrayList<J>.class);
        subtype = type;
    }
}

class IntListProp extends ListProp<Integer> {
    public IntListProp() {
        super(Integer.class);
    }
}

但是super(ArrayList<J>.class)当然不会编译,super(ArrayList.class)也不会编译.解决此问题的最佳方法是什么?

But of course super(ArrayList<J>.class) does not compile, neither does super(ArrayList.class) . What's the best way to solve this?

推荐答案

您需要使ListProp类编译的通用功夫是这一行:

The generics kung fu you need to make your ListProp class compile is this line:

super((Class<List<T>>)(Class<?>)List.class); // compiles

尝试直接从List.class投射到Class<List<T>>:

super((Class<List<T>>)List.class); //compile error

导致编译错误:

不可转换的类型;无法将'java.lang.Class'强制转换为'java.lang.Class>

Inconvertible types; cannot cast 'java.lang.Class' to 'java.lang.Class>

但是,如果您首先强制转换为类型类Class<?>,尽管类型未知,您可以然后将其强制转换为所需的类型类.

But if you first cast to typed class Class<?>, albeit an unknown type, you can then cast it the desired typed class.

然后是完全可编译的ListProp类.

The full compilable ListProp class is then.

class ListProp<T> extends Prop<List<T>> {
    Class<T> subtype;
    public ListProp(Class<T> type) {
        super((Class<List<T>>)(Class<?>)List.class); // magic double cast
        subtype = type;
    }
}


在需要特殊代码来创建/返回列表的情况下,您可能会考虑的其他事情是Propt的类型化吸气剂:


Something else you may consider, in case you need special code for creating/returning a list, is a typed getter for t on Prop:

public T getT() {
    return t;
}

然后您可以在ListProp中协变地覆盖它,以返回List<T>

which you can then covariantly override in ListProp to return a List<T>

@Override
public List<T> getT() {
    return Arrays.asList(subtype.newInstance()); // or whatever
}


应该注意的是,只有在实现使用类的情况下才需要类令牌,示例代码中未显示该类令牌.如果您实际上并未使用类标记,则可以让类型推断为您进行键入.


It should be noted that you only need the class token if your implementation uses the class, which is not shown in your example code. If you don't actually use the class token, you can let type inference do the typing for you.

这篇关于如何使用类标记保留嵌套泛型的泛型类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆