如何使用此 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
的风险。
我有一个摘要 class A<T>
带有通用通配符 T。A 有两个扩展,
public class A1 extends A<Integer> {...}
和
public class A2 extends A<String> {...}
现在我有另一个 class,我们称它为 B,它基本上是 A1 或 A2 的集合。所以我将它定义为泛型类型 T extends A:
的 classpublic 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
的风险。