0

Java 中解决类型擦除的标准方法是将类标记传递给构造函数。例如,我们可以像这样定义一个通用属性类:

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);
    }
}

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

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). 解决这个问题的最佳方法是什么?

4

2 回答 2

4

ListProp你需要让你的类编译的泛型功夫是这一行:

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

尝试直接从List.classto投射Class<List<T>>

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

导致编译错误:

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

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

然后是完整的可编译ListProp类。

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;
    }
}

t如果您需要特殊代码来创建/返回列表,您可能会考虑的其他内容是on的类型化 getter Prop

public T getT() {
    return t;
}

然后你可以协变地覆盖它ListProp以返回一个List<T>

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

应该注意的是,如果您的实现使用类,您只需要类令牌,这在您的示例代码中没有显示。如果您实际上不使用类令牌,则可以让类型推断为您进行输入。

于 2016-05-15T00:00:01.733 回答
0

小介绍

我知道一种解决问题的方法。类型擦除用于在编译后擦除类型,因为它们不需要运行。这可能就是为什么您不能只使用 type 访问类 List 的原因。List 本身使用泛型,因此为此提供一个类是没有意义或不可能的,因为在您的情况下, T 实际上是列表元素的类型。该类实际上是 ArrayList。您正在寻找的是您正在使用的集合类型和您正在使用的元素类型。我已经稍微更改了您的代码,以便您可以接受这两种类型的构造函数。


  1. T 现在是集合中元素的类型
  2. J 现在是 Collection 类型

代码

  class ListProp<T, J> extends Prop<T, J> {
            Class<T> subtype;
            Class<J> subtypeElementList:

            public ListProp(Class<T> typeElement, Class<J> typeList) {
                super(typeElement, typeList);
                subtype = typeElement;
                subtypeElementList = typeList;
            }

        }

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

        class Prop<T, J> {
            // TODO: Maybe here the elements again? Depends on what you want to do...
            //
            // or maybe just use the integer as you had previously.
            public Prop(Class<T> integerClass, Class<J> arrayListClass) {

            }
        }
于 2016-05-14T20:37:15.683 回答