37

有没有区别

<N extends Number> Collection<N> getThatCollection(Class<N> type)

Collection<? extends Number> getThatCollection(Class<? extends Number>)
4

2 回答 2

38

它们为方法公开不同的接口和契约。

第一个声明应该返回一个元素类型与参数类相同的集合。编译器推断类型N(如果未指定)。因此,在使用第一个声明时,以下两个语句是有效的:

Collection<Integer> c1 = getThatCollection(Integer.class);
Collection<Double> c2 = getThatCollection(Double.class);

第二个声明没有声明返回的 Collection 类型参数与参数类之间的关系。编译器假定它们是不相关的,因此客户端必须使用返回的类型 as Collection<? extends Number>,而不管参数是什么:

// Invalid statements
Collection<Integer> c1 = getThatCollection(Integer.class);   // invalid
Collection<Double> c2 = getThatCollection(Double.class);   // invalid
Collection<Number> cN = getThatCollection(Number.class);   // invalid

// Valid statements
Collection<? extends Number> c3 = getThatCollection(Integer.class);  // valid
Collection<? extends Number> c4 = getThatCollection(Double.class);  // valid
Collection<? extends Number> cNC = getThatCollection(Number.class);  // valid

推荐

如果返回的类型参数和传递的参数之间确实存在类型关系,那么使用第一个声明会更好。如上所述,客户端代码更清晰。

如果关系不存在,那么最好避免第二次声明。具有带界通配符的返回类型会强制客户端在任何地方使用通配符,因此客户端代码变得杂乱无章且不可读。Joshua Bloch 强调您应该避免在返回类型中使用有界通配符(幻灯片 23)。虽然返回类型中的有界通配符在某些情况下可能很有用,但恕我直言,结果代码的丑陋应该覆盖好处。

于 2009-11-17T17:13:25.943 回答
-3

在这种特殊情况下,不。但是,第二个选项更灵活,因为它允许您返回包含与集合参数包含的类型不同类型的元素(即使它也是数字)的集合。

具体例子:

Collection<? extends Number> getRoot(Class<? extends Number> number){ 
    ArrayList<Integer> result=new ArrayList<Integer>();
    result.add(java.util.Math.round(number); 
    return result) 
}
于 2009-11-17T17:20:12.320 回答