它们暴露不同的接口和方法的约定。
第一个声明应该返回一个集合,其元素类型与参数类相同。编译器推断N的类型(如果未指定)。因此,以下两个语句在使用第一个声明时有效:
Collection c1 = getThatCollection(Integer.class);
Collection c2 = getThatCollection(Double.class);
第二个声明不声明返回的Collection类型参数与参数类之间的关系。编译器假定它们是不相关的,因此客户端必须使用返回的类型作为Collection
// Invalid statements
Collection c1 = getThatCollection(Integer.class); // invalid
Collection c2 = getThatCollection(Double.class); // invalid
Collection 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)。虽然有界通配符在返回类型可能是有用的在一些情况下,结果代码的丑陋应该,IMHO,覆盖的好处。