当前位置: 首页 > 知识库问答 >
问题:

上界通配符的好处是什么?

姜玮
2023-03-14
static <T extends Number> void gMethod (ArrayList <T> list) {}
ArrayList <Integer> intList = new ArrayList();
gMethod(intList); // allowed

为了进一步说明受限制于Number的泛型将接受Number或它的任何子类的类型参数:

class Thing <T extends Number> {}
Thing <Number> numThing = new Thing();
Thing <Integer> intThing = new Thing();
Thing <Double> dubThing = new Thing(); // All three instances work

鉴于此,我看到使用上限有界通配符与有界泛型相比的唯一好处是,可以声明上限有界通配符类型参数,而不依赖于类或方法已经声明的类型参数。还有更重要的好处我错过了吗?

共有1个答案

罗浩然
2023-03-14

“…我能看到的使用上限有界通配符与有界泛型通配符的唯一好处…”

如果您的用例只要求您一次使用一个东西,那么您所描述的简单使用场景就是您所需要的。

但最终会有一个用例,在这个用例中,您需要处理不同种类的东西。这时,您需要从工具箱中提取稍微高级一些的多态性。

“……我错过了一个更重要的好处吗?……”

一个超级重要的好处,听起来好像你错过了,是类型之间的替代关系;叫做协方差。

例如,既然这样做是合法的:

Integer[] intAry = {2,4,6,8};
Number[] numAry = intAry;
    

那么直觉上,似乎你应该能够做到这一点:

List<Integer> intList = List.of(8,6,7,5,3,0,9);
List<Number> numList = intList; // but this fails to compile

带有上限的通配符有效地使集合变得协变:

List <? extends Number> numList = intList;

由于Integer扩展Number:

Thing<Number> numThing = new Thing<>();
Thing<Integer> intThing = new Thing<>();
numThing = intThing; // but this fails to compile
Thing<? extends Number> numThing = new Thing<>();        
numThing = intThing; /* That makes sense! */

同样处理方法。在此声明中:

public static void use(Thing<Number> oneThing){ 
    /*...*/
}

这将无法编译:

Thing<Integer> intThing = new Thing<>();        
use(intThing); /*  error: no suitable method found for use(Thing<Integer>) */

带有上限的通配符可以使用东西,就像您直觉上认为的那样:

public static void use(Thing<? extends Number> anyThing){ 
    /* ...*/
}

...
Thing<Integer> intThing = new Thing<>();        
use(intThing); /* Perfectly fine! */
 类似资料:
  • null 为什么我不能在MyList中添加对象。因为如果我们使用super,这意味着这个列表可以包含在Java类的继承制度中等于或高于number的对象。因此应该按照该语句在列表中添加新的Object()。 多谢了。

  • 上限通配符下限通配符 有人能帮我理解一下吗?

  • 我有下面的地图 有时有一个列表,有时有一个集合作为值。现在我想获取值,但有一个问题,它无法编译。 我知道我可以这样做: 但我有兴趣了解它应该如何与通用getOrDefault方法一起工作

  • 现在我正在尝试构建一个(灵活的)列表,并向其中添加不同类型的对象。 我可以将的实例添加到。但是,当我试图将或的实例添加到同一个列表中时,会出现编译错误。是否足够灵活,可以使用或其超级类的任何实例?和在层次结构树中位于较高位置。为什么我不能将这些实例添加到列表中?

  • null 编译,我真的不明白为什么。基本上与第1行相同的问题。是的超类,如何将超类的成员放入此中? 编译。与第1行相同的问题。

  • 问号(?)代表通配符,代表泛型中的未知类型。 有时您可能希望限制允许传递给类型参数的类型。 例如,对数字进行操作的方法可能只想接受Number或其子类的实例。 要声明一个上限的Wildcard参数,请列出?,后跟extends关键字,后跟其上限。 例子 (Example) 以下示例说明了如何使用extends来指定上限通配符。 package com.wenjiangs; import java.