java中泛型类型的子类型

时间:2015-07-01 10:27:43

标签: java generics wildcard

我对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

1 个答案:

答案 0 :(得分:1)

class2中设置的方法会列出一个列表,其中所有元素的类型为TTNumber或任何子类Number:< / p>

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

}

这会将输入参数list分配给numberList,并且两者都只能包含由T表示的一种类型的元素(T需要{{1 }}或Number的子类型,例如Number)。

另一方面,方法Integer将返回元素列表,其中每个元素的类型为getT表示<T extends Integer>必须为TInteger的子类之一。我们需要了解此Integer与上面方法T中定义的set不同。

现在出现以下一行:

Class2.set(Class2.get());

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

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

混淆似乎在:List <? extends Integer>List <T extends Number>之间缩小。所以IMO的区别在于:

  1. List <? extends Integer>表示它是一个“未知类型”列表,它将扩展Integer并根据规则 PECS (Producer Extends Consumer Super)这可以生成元素但是不能消耗元素。
  2. List<T extends Integer>是包含超类Integer的类型列表,我们可以将这些元素读取或添加到列表中。

    在旁注上,签名应该是List <? extends Number>而不是List <? extends Integer>,因为Integerfinal,并且不能归类。

  3. 使用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

    中所述
      

    IntegerNumber的子类型,但List<Integer>不是子类型   List<number>,而这些根本没有关系。常见的   List<Number>List<Integer>的父级为List<?>

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