之间有区别吗?
<N extends Number> Collection<N> getThatCollection(Class<N> type)
和
Collection<? extends Number> getThatCollection(Class<? extends Number>)
答案 0 :(得分:36)
它们暴露了该方法的不同接口和契约。
第一个声明应该返回一个集合,其元素类型与参数类相同。编译器推断出N
的类型(如果未指定)。因此,在使用第一个声明时,以下两个语句是有效的:
Collection<Integer> c1 = getThatCollection(Integer.class);
Collection<Double> c2 = getThatCollection(Double.class);
第二个声明不声明返回的Collection类型参数与参数类之间的关系。编译器假定它们是不相关的,因此无论参数是什么,客户端都必须使用返回的类型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强调你应该Avoid Bounded Wildcards in Return Types(幻灯片23)。虽然返回类型中的有界通配符可能有用,但在某些情况下,结果代码的丑陋应该恕我直言。
答案 1 :(得分:-3)
在这种特殊情况下,没有。但是第二个选项更灵活,因为它允许你返回一个包含不同类型元素的集合(即使它也是一个数字)而不是集合参数包含的类型。
具体例子:
Collection<? extends Number> getRoot(Class<? extends Number> number){
ArrayList<Integer> result=new ArrayList<Integer>();
result.add(java.util.Math.round(number);
return result)
}