嵌套泛型继承

2022-09-02 21:21:47

我有以下类:

class Field<T> {

  private final Class<T> type;

  public Field(Class<T> type) {
    this.type = type;
  }
}

class Pick<V> {
  private final V value;
  private final Class<V> type;

  public Pick(V value, Class<V> type) {
    this.value = value;
    this.type = type;
  }
}

和问题相关的类:

class PickField<T> extends Field<Pick<T>> {

  public PickField(Class<Pick<T>> type) {
    super(type);
  }
}

现在,这似乎已被编译器接受。不幸的是,我不知道/理解如何创建一个新的实例,例如用于 picks。PickFieldString

当然,这确实不起作用:
new PickField<String>(Pick.class)

这是不允许的(我想我明白为什么):
new PickField<String>(Pick<String>.class)

那么该怎么做呢?还是整个方法以某种方式“闻到”?


答案 1

我认为应该只用实例进行参数化。PickFieldPick

所以这样做应该没问题:

class PickField<T extends Pick<T>> extends Field<T> {

    public PickField(Class<T> c) {
        super(c);
    }
}

然后,您可以使用以下命令实例化它:

PickField<SomeSpecificPick> instance = new PickField<>(SomeSpecificPick.class);

其中定义为:SomeSpecificPick

public class SomeSpecificPick extends Pick<SomeSpecificPick> {

    public SomeSpecificPick(SomeSpecificPick value, Class<SomeSpecificPick> type) {
        super(value, type);
    }
}

更多信息(与主题相关):


答案 2

这里有各种问题。

首先,正如您所指出的,您无法在编译时获取参数化类型的类,因为只有一个类是为泛型类型编译的,而不是为每个给定的类型参数编译一个类(例如,成语不编译,实际上没有意义)。Pick<String>.class

同样,正如您所提到的,将构造函数参数化 only 不会再次编译,因为签名不匹配。PickField<String>Pick.class

您可以使用运行时习惯用语来推断正确的参数,但这会产生另一个问题:由于类型擦除,您的 类型参数在运行时将是未知的。Pick<T>T

因此,您可以通过显式强制转换来参数化构造函数调用,如下所示:

new PickField<String>(
    (Class<Pick<String>>)new Pick<String>("", String.class).getClass()
);

...它将使用“未选中的投射”警告进行编译()。Type safety: Unchecked cast from Class<capture#1-of ? extends Pick> to Class<Pick<String>>

真正的问题可能是为什么你需要知道你在课堂上的价值。typePick


推荐