有界通配符和types参数有什么区别?

有没有区别

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

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

他们暴露不同的接口和合同的方法。

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

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

第二个声明没有声明返回的Collectiontypes参数与参数类之间的关系。 编译器假定它们是不相关的,所以客户端将不得不使用返回的types作为Collection<? extends Number> Collection<? extends Number> ,而不pipe参数是什么:

 // 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 

build议

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

如果这种关系不存在,那么最好避免第二个声明。 使用有界通配符的返回types强制客户端在任何地方都使用通配符,因此客户端代码变得分崩离析,无法读取。 约书亚布洛克emphisize,你应该避免返回types有限通配符 (幻灯片23)。 虽然返回types有界的通配符可能是有用的是一些情况下,结果代码的丑陋,恕我直言,恕我直言,覆盖的好处。

在这个特殊的情况下,没有。 然而,第二个选项更加灵活,因为它允许您返回包含不同types元素(即使它也是Number)的集合,而不是包含collection参数的types。

具体例子:

 Collection<? extends Number> getRoot(Class<? extends Number> number){ ArrayList<Integer> result=new ArrayList<Integer>(); result.add(java.util.Math.round(number); return result) }