嵌套泛型继承

JDC*_*JDC 18 java generics inheritance

我有以下课程:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

和问题所涉及的类:

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

  public PickField(Class<Pick<T>> type) {
    super(type);
  }
}
Run Code Online (Sandbox Code Playgroud)

现在这似乎被编译器接受了.不幸的是,我不知道/理解如何创建一个新的实例PickField,例如 String选择.

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

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

那怎么办呢?或者整个方法是否以某种方式" "?

Kon*_*kov 15

我认为PickField应该Pick只用实例参数化.

所以这样做应该没问题:

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

    public PickField(Class<T> c) {
        super(c);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用以下方法实例化它:

PickField<SomeSpecificPick> instance = new PickField<>(SomeSpecificPick.class);
Run Code Online (Sandbox Code Playgroud)

其中SomeSpecificPick定义为:

public class SomeSpecificPick extends Pick<SomeSpecificPick> {

    public SomeSpecificPick(SomeSpecificPick value, Class<SomeSpecificPick> type) {
        super(value, type);
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Men*_*ena 7

这里有各种各样的问题.

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

再次提到,由于签名不匹配PickField<String>,因此Pick.class 仅使用参数化构造函数不会再次编译.

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

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

new PickField<String>(
    (Class<Pick<String>>)new Pick<String>("", String.class).getClass()
);
Run Code Online (Sandbox Code Playgroud)

...将使用"未经检查的强制转换"警告(Type safety: Unchecked cast from Class<capture#1-of ? extends Pick> to Class<Pick<String>>)进行编译.

真正的问题可能是为什么你需要知道的价值type在你的Pick班级.

  • @JDC Semantics IMO.你提到它的"气味"就是你想要知道你的泛型类`Pick`在实例范围内被参数化的类型.这通常会玷污仿制药背后的概念,并可能表明您的设计存在更广泛的问题. (2认同)