我对java中泛型的子类型感到困惑。我在下面有一个示例。
public class Class2{
public static <T extends Number> void set(List<T> list){
List<T> numberList = list;;
}
public static <T extends Integer> List<T> get(){
List<T> list = new ArrayList<T>();
return list;
}
}
//Does this line is the same as the two below line?
Class2.set(Class2.get());
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numberList = intList;
我的问题:
之间有什么不同Class2.set(Class2.get());
和
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numberList = intList;
更新#1: 变化
public static <T> void set(List<T> list)
到
public static <T extends Number> void set(List<T> list)
更新#2: 看一下图片(从docs.oracle中获取关于java中的泛型) 链接:https://docs.oracle.com/javase/tutorial/figures/java/generics-wildcardSubtyping.gif
从图像中我们知道List<? extends Integer>
是List<? extends Number>
的子类型。我们可以为List<? extends Integer>
的变量指定List<? extends Number>
变量。
在上面的示例中,我是否真的为List<T extends Integer>
变量分配了List<T extends Number>
变量?如果是,List<T extends Number>
是List<T extends Integer>
的子类型吗?你能不能这样我如何证明它是否存在?
P / S:oracle文档的链接帖子:https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html
答案 0 :(得分:1)
class2
中设置的方法会列出一个列表,其中所有元素的类型为T
,T
为Number
或任何子类Number
:< / p>
public static <T extends Number> void set(List<T> list){
List<T> numberList = list;
}
这会将输入参数list
分配给numberList
,并且两者都只能包含由T
表示的一种类型的元素(T
需要{{1 }}或Number
的子类型,例如Number
)。
另一方面,方法Integer
将返回元素列表,其中每个元素的类型为get
,T
表示<T extends Integer>
必须为T
或Integer
的子类之一。我们需要了解此Integer
与上面方法T
中定义的set
不同。
现在出现以下一行:
Class2.set(Class2.get());
实际上使用每个元素具有相同类型numberList
的元素初始化T
。另一方面,我们有:
List<? extends Integer> intList = new ArrayList<>();
混淆似乎在:List <? extends Integer>
和List <T extends Number>
之间缩小。所以IMO的区别在于:
List <? extends Integer>
表示它是一个“未知类型”列表,它将扩展Integer
并根据规则 PECS (Producer Extends Consumer Super)这可以生成元素但是不能消耗元素。 List<T extends Integer>
是包含超类Integer
的类型列表,我们可以将这些元素读取或添加到列表中。
在旁注上,签名应该是List <? extends Number>
而不是List <? extends Integer>
,因为Integer
是final
,并且不能归类。
使用extends
List<? extends Number> list1 = new ArrayList<Number>(); // Number "extends" Number (in context)
List<? extends Number> list2 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> list3 = new ArrayList<Double>(); // Double extends Number
使用super
List<? super Integer> list4 = new ArrayList<Integer>(); // Integer is a "superclass" of Integer
List<? super Integer> list5 = new ArrayList<Number>(); // Number is a superclass of Integer
List<? super Integer> list6 = new ArrayList<Object>(); // Object is a superclass of Integer
修改强>
方法get
返回类型为T
的元素列表(T可以是Integer
或子类型):
List<Integer> list1 = Class2.get();
现在,对于set
方法,以下所有方法都可以使用:
List<Integer> list1 = Class2.get();
Class2.set(list1);
List<Number> list2 = new ArrayList<Number>();
Class2.set(list2);
List<Integer> list3 = new ArrayList<Integer>();
Class2.set(list3);
正如doc
中所述
Integer
是Number
的子类型,但List<Integer>
不是子类型List<number>
,而这些根本没有关系。常见的List<Number>
和List<Integer>
的父级为List<?>
。
正如我上面所解释的那样,List<? extends Integer>
会接受Integer
而List<?extends Number>
会更加放松。所有这些之间的关系由image表示。