Java 泛型中如何使用逆变?
在 Java 中,协变允许 API 设计者指定可以将实例概括为某种类型或该类型的任何子类型。例如:
List<? extends Shape> shapes = new ArrayList<Circle>();
// where type Circle extends Shape
逆变则相反。它允许我们指定一个实例可以被泛化为某种类型或超类型。
List<? super Shape> shapes = new ArrayList<Geometry>();
// where Shape extends Geometry
Java 泛型的逆变有何用处?您什么时候会选择使用它?
In Java, covariance allows the API designer to specify that an instance may be generalised as a certain type or any of that type's subtypes. For example:
List<? extends Shape> shapes = new ArrayList<Circle>();
// where type Circle extends Shape
Contravariance goes the other way. It allows us to specify that an instance may be generalised as a certain type or supertype.
List<? super Shape> shapes = new ArrayList<Geometry>();
// where Shape extends Geometry
How is Java generic's contravariance useful? When would you choose to use it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
以下是 Java 泛型和集合 的相关摘录:
2.4。 Get 和 Put 原则
尽可能插入通配符可能是一个好习惯,但是您如何决定
使用哪个通配符?哪里应该使用
extends
,哪里应该使用super
,哪些地方不适合使用通配符?
幸运的是,有一个简单的原则可以决定哪种方法是合适的。
我们已经在 copy 方法的签名中看到了这一原理:
该方法从源 src 中获取值,因此使用
extends
通配符声明它,并将值放入目标 dst,因此它是用
super
通配符声明的。每当您使用迭代器时,您都会从结构中获取值,因此请使用
extends
通配符。这是一个方法,它接受数字集合,将每个数字转换为双精度值,
并总结它们:
Here's a relevant excerpt from Java Generics and Collections:
2.4. The Get and Put Principle
It may be good practice to insert wildcards whenever possible, but how do you decide
which wildcard to use? Where should you use
extends
, where should you usesuper
,and where is it inappropriate to use a wildcard at all?
Fortunately, a simple principle determines which is appropriate.
We already saw this principle at work in the signature of the copy method:
The method gets values out of the source src, so it is declared with an
extends
wildcard,and it puts values into the destination dst, so it is declared with a
super
wildcard.Whenever you use an iterator, you get values out of a structure, so use an
extends
wildcard. Here is a method that takes a collection of numbers, converts each to a double,
and sums them up:
好吧,你的第二个例子将允许你写:
而你不能用第一个形式做到这一点。我承认,它不像协方差那么有用。
它可以有用的一个领域是比较。例如,考虑一下:
您可以使用它来比较任意两个形状...因此,如果我们也可以使用它来对
List
进行排序,那就太好了。例如,圆>
。幸运的是,我们可以通过逆变来做到这一点,这就是为什么Collections.sort
存在重载:Well, your second example would allow you to write:
whereas you couldn't do that with the first form. It's not useful as often as covariance, I'll grant you.
One area where it can be useful is in terms of comparisons. For example, consider:
You can use that to compare any two shapes... so it would be nice if we could also use it to sort a
List<Circle>
for example. Fortunately, we can do that with contravariance, which is why there's an overload forCollections.sort
of:例如,当实现 Collections.addAll()< /a> 方法,您需要一个可以包含某种类型 T 或 T 的超类型的集合。该方法如下所示:
For example, when implementing the Collections.addAll() method, you need a collection that can contain some type T or a supertype of T. The method then looks like: