为什么在Java泛型中List <Integer>是List <的子类型?扩展整数>?

时间:2019-10-11 01:52:45

标签: java generics

在Java教程中:

https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html

它表示List<Integer>List<? extends Integer>的子类型,我发现这是违反直觉的,因为? extends Integer表示任何Integer或{{1的子类型}},其背后的设计考虑是什么?

引用:

https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html

  

术语IntegerList<Number>更具限制性,因为前者仅匹配Number类型的列表,而后者匹配Number类型或其任何子类的列表。

我也对List<? extends Number>的子类型List<? super Number>感到困惑。

enter image description here

3 个答案:

答案 0 :(得分:0)

令我惊讶的是,给定Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?,根本没有父类型/子类型的关系。但是,既然有,我只能就为什么允许这样做以及为什么要绕开它的方式提出自己的想法/猜测。

编辑添加:进一步检查,我不应该感到惊讶,因为它们的关系与“狗和动物”相同-即。 List<Animal> List<? extends Animal>的子类型。

话虽如此,我想这是为了使对这些列表的其他引用保持“安全”。例如,考虑使用以下可能的情况:

public class PositiveInteger extends Integer {

那么我们可以拥有

List<Integer> listInteger = new ArrayList<>();
List<Integer> myIntegers = listInteger;
List<PositiveInteger> listPositiveInteger = new ArrayList<>();
List<PositiveInteger> myPositives = listPositiveInteger;

现在,超类型和子类型的想法是我们可以为超类型分配子类型引用,反之亦然。例如我们可以拥有:

Animal animal = myDog;

但不是

Dog rex = someAnimal;

所以让我们将该逻辑应用于列表。

List<? extends Integer> positives = listInteger;

这是您所允许的。需要注意的重要一点是,我们现有的myIntegers变量是安全的-它仍将仅包含Integer s。

此语句的唯一“危险”是,它使positives.get(0)可能会收到负整数-但这根本不是危险(只是我们的变量命名存在问题),因为此处的语言语法仅指整数,不涉及PositiveIntegers。就语言而言,我们同样可以拥有:

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

现在,如果我们允许的话:

List<Integer> integers = listPositiveInteger;

现在系统的这个位是安全的-但是我们的myPositives变量呢? myPositives的所有用户都完全有权期望只收到PositiveIntegers,但是没有什么阻止我们拥有:

integers.add(-123);

由于该列表对象与myPositives是相同的列表对象,因此我们将-123添加到该列表-隐含地影响系统其余部分的更危险的前景。

答案 1 :(得分:0)

  

为什么在Java泛型List<Integer>中是List<? extends Integer>的子类型?

因为否则您将无法执行以下操作:

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

就个人而言,我会发现上述导致错误的情况是直觉相反的情况。当您拥有List<? extends Integer>时,就是说List可能包含IntegerInteger 1 的某些子类型或{{ 1}}的子类型 1 Integer当然满足了这些要求。

List<Integer>List<? super Number>的子类型的参数非常相似。如果不是这种情况,那么您将无法执行以下操作:

List<? super Integer>

List<? super Number> list1 = new ArrayList<>(); List<? super Integer> list2 = list1; 的全部含义是List<? super Integer>能够使用类型ListInteger的某些超类型的对象。 Integer满足这些要求。

有些链接可能会有用:

我也建议您浏览上述问答的链接/相关部分。


1。因为类为List<? super Number>,所以说“ Integer的子类型”可能会造成混淆,但希望它仍然有意义。

答案 2 :(得分:0)

尝试像这样查看? super T子类型:

<? super Number><Number><Serializable><Object>

的通配符

<? super Integer><Integer><Number><Serializable><Object>

的通配符

Integer可以放置在所有可能的<? super Number>中,因此<? super Integer>可以是<? super Number>(IS A关系,所以<? super Number>是{{ 1}})

<? super Integer>不能放在所有可能的Number中(不能在期望<? super Integer>的地方放置任何Number),所以Integer可以成为<? super Number>