如何使用此 class 的通用类型 (Java) 的通用类型?

How do I use the generic type of this class's generic type (Java)?

我有一个摘要 class A<T> 带有通用通配符 T。A 有两个扩展,

public class A1 extends A<Integer> {...}

public class A2 extends A<String> {...}

现在我有另一个 class,我们称它为 B,它基本上是 A1 或 A2 的集合。所以我将它定义为泛型类型 T extends A:

的 class
public class B<T extends A> {...}

我希望能够做的是,在 B 中,创建 return T 的泛型类型的方法。例如,

B<A1> foo = new B<A1>;
foo.get(); // returns Integer, corresponding to A1's generic type

B<A2> bar = new B<A2>;
bar.get(); // returns String, corresponding to A2's generic type

是否可以在 Java 中执行此操作?在声明 B 的方法时,我无法弄清楚要放置什么 return 类型(如果我想让 B 到 return T,我会放置 public T get() {...},但我实际上想要 return 参数化类型 of T)。或者有没有比我处理它的方式更好地解决这个问题的模式?

谢谢。

您可以为 B 声明第二个类型参数,并将其作为 A

的参数化
class B<K, T extends A<K>> {
    public K get() {
        // actual implementation
        return null;
    }
}

然后声明你的变量

B<String, A2> var = new B<>();
String ret = var.get();

What is a raw type and why shouldn't we use it?

我想提供一个示例,以帮助您更好地理解为什么我们需要两个泛型类型参数。首先,A 及其直接子 classes .

的示例声明
class A<T> {

    private T value;

    public A(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }   
}

class A1 extends A<Integer> {
    A1(Integer i) {
        super(i);
    }
}

class A2 extends A<String> {
    A2(String str) {
        super(str);
    }
}

现在,B class 声明。请注意,它如何在其定义中引用这两种泛型类型以提供对包装的 A subclass.

成员的访问
public class B<T, X extends A<T>> {

    private X data;

    public B(X data) {
        this.data = data;
    }

    public T get() {
        return data.getValue();
    }

    public static void main(String[] args) {

        B<Integer, A1> foo = new B<Integer, A1>(new A1(10));
        System.out.println(foo.get()); // returns Integer

        B<String, A2> bar = new B<String, A2>(new A2("Ten"));
        System.out.println(bar.get()); // returns String
    }
}

如果只切换到一种类型参数,则有两种选择。

你要么保持 A subclass 的类型像

public class B<T extends A<?>> {

    private T data;

    public B(T data) {
        this.data = data;
    }

    public Object get() {
        return data.getValue();
    }

    ...
}

或者,getter 的实际 return 类型。

public class B<T> {

    private T value;

    @SuppressWarnings("unchecked")
    public B(A<?> data) {
        this.value = (T) data.getValue();
    }

    public T get() {
        return value;
    }

    ... 
}

请注意,这两种解决方案都是脆弱的。

一个返回 Object 并需要使用 instanceof 来正确地转换它,而另一个则更脆弱 unchecked 转换。由于您没有提供所需的通用类型,因此您已经限制了 class 设计和 运行 现在获得 ClassCastException 的风险。