我有一个带有通用通配符T的抽象类A<T>
。有两个扩展名A,
public class A1 extends A<Integer> {...}
和
public class A2 extends A<String> {...}
现在我有另一个类,我们称之为B,它基本上是A1或A2的集合。所以我把它定义为一类泛型类型T extends A:
public class B<T extends A> {...}
我希望能够在B中创建返回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的方法时,我无法确定要返回的返回类型(如果我想让B返回T,我会放置public T get() {...}
,但我实际上想要返回参数化类型 T)。或者是否有一种模式可以比我接近它的方式更好地解决这个问题?
感谢。
答案 0 :(得分:3)
您可以为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();
答案 1 :(得分:1)
我想提供一个示例,可以帮助您更好地理解为什么我们需要两个泛型类型参数。首先,A
及其直接子类的示例声明。
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
类声明。请注意,它如何引用其定义中的泛型类型以提供对包装的A
子类成员的访问。
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
子类的类型,如
public class B<T extends A<?>> {
private T data;
public B(T data) {
this.data = data;
}
public Object get() {
return data.getValue();
}
...
}
或者,实际的return
类型的getter。
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
正确投射,另一个更加脆弱,并且未经检查投射。既然您没有提供所需的通用类型,那么您已经限制了您的班级设计,并冒着现在获得ClassCastException
的风险。