我是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
对象的功能。实际上,如果
B1
和B2
是从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
后,实际上就选择了该集合的具体评估。