我是Java新手。有人可以告诉我这行是什么意思吗?

class_A
...
Iterable< ? extends iface_classB> getThings();

其中iface_classB可以是classB的接口/抽象。

我写的东西时出现错误:
class_A myA = new classA()

Iterable< impl_of_iface_classB > anIterator = myA.getThings()

我想知道模板中的问号。我的猜测是应该是从iface_classB派生的任何内容,但似乎我错了。

非常感谢您的回答。

最佳答案

您所做的假设与实际情况相反:

Iterable<? extends iface_classB> getThings();

表示getThings()返回具有至少 iface_classB功能的对象的可迭代对象。因此,您不能将getThings()的结果分配给任何Iterable< impl_of_iface_classB >,因为您只能确保这些对象公开了iface_classB的功能。

例如,如果getThings()返回的对象实际上是Iterable<impl2_of_iface_classB>,那么impl2_of_iface_classB扩展了iface_classB怎么办?
可迭代对象将不具有impl_of_iface_classB对象的功能。

实际上,如果B1B2是从B派生的,则完全允许具有
A<? extends B> x;
A<B1> y;
A<B2> z;

x = y;
x = z;

因此,就通用参数的含义而言,不能依赖getThings():只能将其用作“普通” iface_classB

更重要的是,您希望能够分配给Iterable<iface_classB>,但是您不能这样做(除非您执行未经检查的强制类型转换,否则)。这是因为通配符本质上是指“一组可行的通用参数”。想象一下,用您使用的具体通用参数替换通配符:如果参数不匹配,则由于类型不兼容而出现通常的编译时错误。编译器必须考虑所有情况,不允许您这样做。因此,
A<? extends B> x;
A<B> y = x;

虽然有效,但不允许这样做,因为x可能被分配了与B不同的参数,从而为分配的两侧产生了不同的类型。反之,
A<B> x;
A<? extends B> y = x;

之所以被允许,是因为y的类型表示替代集的集合,并且该集合包括A<B>。像上面这样分配y后,实际上就选择了该集合的具体评估。

07-24 13:09