有界通配符和类型参数有什么区别? [英] What is the difference between bounded wildcard and type parameters?

查看:173
本文介绍了有界通配符和类型参数有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



 < N extends Number>收集和LT; N> getThatCollection(Class< N>类型)

 收集和LT ;?扩展Number> getThatCollection(Class< ;? extends Number>)


解决方案

不同的接口和方法的合同。

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

 集合<整数> c1 = getThatCollection(Integer.class); 
收藏集< Double> c2 = getThatCollection(Double.class);

第二个声明没有声明返回的Collection类型参数与参数类之间的关系。编译器假定它们不相关,所以客户端必须使用返回的类型作为 Collection <?扩展Number> ,无论参数是什么:

  //无效语句
收集和LT;整数> c1 = getThatCollection(Integer.class); //无效
收藏集< Double> c2 = getThatCollection(Double.class); //无效
Collection< Number> cN = getThatCollection(Number.class); //无效

//有效语句
集合<?扩展Number> c3 = getThatCollection(Integer.class); //有效
收藏<?扩展Number> c4 = getThatCollection(Double.class); //有效
收藏<?扩展Number> cNC = getThatCollection(Number.class); //有效

建议

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



如果关系不存在,那么避免第二个声明更好。使用有界通配符的返回类型会强制客户端在任何地方使用通配符,因此客户端代码会变得分崩离析,无法读取。 Joshua Bloch emphisize表示您应该避免返回类型中的有界通配符(幻灯片23 )。尽管返回类型中有界的通配符可能有用,但在某些情况下,结果代码的丑陋应恕我直言,恕不另行通知。


Is there a difference between

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

and

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

解决方案

They expose different interfaces and contract for the method.

The first declaration should return a collection whose elements type is the same of the argument class. The compiler infers the type of N (if not specified). So the following two statements are valid when using the first declaration:

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

The second declaration doesn't declare the relationship between the returned Collection type argument to the argument class. The compiler assumes that they are unrelated, so the client would have to use the returned type as Collection<? extends Number>, regardless of what the argument is:

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

Recommendation

If indeed there is a relationship between the type between the returned type argument and the passed argument, it is much better to use the first declaration. The client code is cleaner as stated above.

If the relationship doesn't exist, then it is still better to avoid the second declaration. Having a returned type with a bounded wildcard forces the client to use wildcards everywhere, so the client code becomes clattered and unreadable. Joshua Bloch emphisize that you should Avoid Bounded Wildcards in Return Types (slide 23). While bounded wildcards in return types may be useful is some cases, the ugliness of the result code should, IMHO, override the benefit.

这篇关于有界通配符和类型参数有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆