泛型 - 下界/上界通配符行为?

3 浏览
0 Comments

泛型 - 下界/上界通配符行为?

我正在尝试理解下界和上界通配符的行为。

在尝试编译下面的代码时遇到了问题。

Collection c = new ArrayList();
c.add(new Object()); // 编译时错误

为了弄清楚问题,我也尝试了下界通配符。幸运或不幸的是,代码可以编译通过,但造成了很多困惑。

Collection c = new ArrayList();
c.add(new Object()); // 编译通过

有人能解释一下这两段代码是如何工作的吗?如果有人能提供更多示例/链接,那就太好了。

如果我在上面做错了什么,请纠正我。

提前感谢。

0
0 Comments

泛型(Generics)是Java中的一个重要特性,它允许我们在编写代码时使用类型参数来增加代码的灵活性和重用性。然而,在使用泛型时,我们可能会遇到一些问题,特别是在处理上限(upper bound)和下限(lower bound)通配符时。

在上面的代码示例中,我们使用了一个ArrayList来存储Number类型的对象,并将其赋值给一个通配符类型为"extends Number"的集合变量c。这意味着集合中的元素可以是任何继承自Number的类型,例如Integer、Double、Float、BigInteger等。因此,我们无法确定列表中实际存储的是哪种Number对象,因为只有特定类型的列表(如List、List、List)才能确保列表中的元素类型。

因此,在使用"extends Number"通配符时,我们无法向其中添加任何元素,因为它可以是上述列表中的任意一种。

与之相反的是,对于"super Number"通配符,表示集合中的每个元素都是Number的祖先类型。在这种情况下,我们可以添加任何Number的超类型或类型到集合中。使用"super Number"通配符,我们保证集合中的元素都是Number的子类或Number类型本身。

然而,我们无法确保实际类型,例如list.get(0)返回的是一个Number,但可能是一个Integer;list.get(1)返回的是一个Number,但可能是一个Float;list.get(2)返回的是一个Number,但可能是一个Double。

使用"extends"通配符用于读取操作,使用"super"通配符用于添加操作。

在Java官方文档中,有一个图示对泛型的上下界行为进行了说明,可以参考此图进行更深入的理解。

至于关于"? super Number"通配符的解释,Jon Skeet在stackoverflow上给出了一个解释。他指出,如果上界是"? super Number",那么Integer、Float和Double是不可能的。因为它们是Number的子类,而"? super Number"匹配的是超类(包括Number本身),而Number的唯一超类是Object。

最后,我们可以通过查看链接中提供的示例代码来进一步理解这些概念。

0
0 Comments

泛型 - 上界/下界通配符行为

在Java中,通配符?表示一个"未知类型"。而Collection<? extends Object>表示一种对象类型的集合。这个"对象类型"可以是任何是Object的子类或者Object本身。具体是哪种类型,编译器是不知道的。

当你尝试向集合中添加一个新的Object时,你是不允许的。这是因为集合的类型是未知的。它可以是一个ArrayList<String>,也可以是一个HashSet<Integer>。所以编译器会这样说:

"如果集合是ArrayList<String>,你不能把一个Object放进去!"

基本上,编译器是过于谨慎,不允许你这样做。

Collection<? super Object>表示一种对象类型的集合。这个"对象类型"可以是任何是Object的超类或者Object本身。在这里,它只能是一个类型 - Object,因为Object没有超类。这就是为什么你可以向集合中添加一个新的Object

即使Object有一个超类,你仍然可以添加一个new Object()。假设Object的超类是MyClass。现在,集合可以是MyClass的集合或者Object的集合。无论是哪个,你都可以向其中添加一个Object

关于Collection<? extends Object>的部分,我完全理解并且也很有道理。但是在Collection<? super Object>的情况下,为什么它可以接受任何超类或者Object类本身?

这就是? super Object的含义。如果A是B的子类,你可以把B添加到A的集合中。这里也是同样的道理。

哦,这是一个打字错误。我是说你可以把A添加到B的集合中。

谢谢,我明白你的意思了。我觉得你最后一段解释得已经足够清楚了。但是在脑海中理解起来确实有些棘手。

0