有界通配符和类型参数之间有什么区别?
2022-09-01 05:25:38
两者之间是否有区别
<N extends Number> Collection<N> getThatCollection(Class<N> type)
和
Collection<? extends Number> getThatCollection(Class<? extends Number>)
两者之间是否有区别
<N extends Number> Collection<N> getThatCollection(Class<N> type)
和
Collection<? extends Number> getThatCollection(Class<? extends Number>)
它们公开了方法的不同接口和协定。
第一个声明应返回其元素类型与参数类相同的集合。编译器推断的类型(如果未指定)。因此,以下两个语句在使用第一个声明时是有效的:N
Collection<Integer> c1 = getThatCollection(Integer.class);
Collection<Double> c2 = getThatCollection(Double.class);
第二个声明不声明返回的集合类型参数与参数类之间的关系。编译器假定它们是不相关的,因此无论参数是什么,客户端都必须将返回的类型用作 :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)。虽然在某些情况下,返回类型中的有界通配符可能很有用,但恕我直言,结果代码的丑陋应该覆盖好处。
在这种特殊情况下,不可以。但是,第二个选项更灵活,因为它允许您返回包含与集合参数所包含的类型不同的类型(即使它也是 Number)的元素的集合。
具体示例:
Collection<? extends Number> getRoot(Class<? extends Number> number){
ArrayList<Integer> result=new ArrayList<Integer>();
result.add(java.util.Math.round(number);
return result)
}