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

发布于 2024-08-11 23:24:06 字数 243 浏览 6 评论 0原文

之间有区别吗

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

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

Is there a difference between

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

and

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云归处 2024-08-18 23:24:06

它们公开了不同的接口和方法契约。

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

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

第二个声明没有声明返回的 Collection 类型参数与参数类之间的关系。编译器假定它们不相关,因此客户端必须将返回类型用作 Collection,无论参数是什么:

// 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 )。虽然返回类型中的有界通配符在某些情况下可能很有用,但恕我直言,结果代码的丑陋应该会覆盖它的好处。

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.

夜光 2024-08-18 23:24:06

在这种特殊情况下,没有。然而,第二个选项更灵活,因为它允许您返回一个集合,其中包含与集合参数包含的类型不同类型的元素(即使它也是数字)。

具体例子:

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

In this particular case, no. however the second option is more flexible since it would allow you to return a collection that contains elements of a different type (even though it would also be a Number) than the type contained by the collection parameter.

Concrete example:

Collection<? extends Number> getRoot(Class<? extends Number> number){ 
    ArrayList<Integer> result=new ArrayList<Integer>();
    result.add(java.util.Math.round(number); 
    return result) 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文