java 中通用类型的子类型

Subtype of generic type in java

我对 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 about generic in java) Link:https://docs.oracle.com/javase/tutorial/figures/java/generics-wildcardSubtyping.gif

从图中我们知道List<? extends Integer>List<? extends Number>的子类型。而我们可以为List<? extends Number>.

的变量赋值List<? extends Integer>的变量

在我上面的例子中,我真的为List<T extends Number>的变量分配了List<T extends Integer>的变量吗?如果是这样,List<T extends Number>List<T extends Integer> 的子类型吗?你能告诉我如何证明它是否存在吗? P/S: Link post Oracle 文档:https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html

class2 中设置的方法采用一个列表,其中所有元素都是 T 类型并且 TNumber 或 class 的任何子 class =20=]:

public static <T extends Number> void set(List<T> list){
        List<T> numberList = list;

}

这会将输入参数list赋值给numberList,两者只能包含一种类型的元素,由T表示(T需要是NumberNumber 的子类型,例如 Integer).

另一方面,方法get将return一个元素列表,其中每个元素都是T类型,<T extends Integer>意味着T必须是 IntegerInteger 的子 class 之一。我们需要明白这个 T 和上面方法 set 中定义的不一样。

现在是下面一行:

Class2.set(Class2.get());

实际上用每个元素都属于同一类型 T 的元素初始化 numberList。另一方面,我们有:

List<? extends Integer> intList = new ArrayList<>();

混淆似乎缩小了:List <? extends Integer>List <T extends Number>。所以 IMO 的区别是:

  1. List <? extends Integer> 表示它是 "unknown type" 的列表,它将扩展 Integer 并且根据规则 PECS(Producer Extends Consumer Super ) 这可以生产元素但不能消耗元素。
  2. List<T extends Integer> 是一个类型为 super class Integer 的列表,我们可以读取或添加元素到列表中。

    附带一提,签名应该是 List <? extends Number> 而不是 List <? extends Integer>,因为 Integerfinal 并且不能被子 classed。

使用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 return 是类型为 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 is a subtype of Number but List<Integer> is not subtype of List<number>, rather these are not related at all. The common parent of List<Number> and List<Integer> is List<?>.

正如我上面所解释的,List<? extends Integer> 将接受 IntegerList<?extends Number> 则更加轻松。所有这些之间的关系由image表示。