来自OCP Java SE 6程序员实践考试的第49页,问题11.我们获得了这样的代码:
class A { }
class B extends A { }
class C extends B { }
public class Carpet<V extends B> {
public <X extends V> Carpet<? extends V> method(Carpet<? super X> e) {
// insert code here
}
}
我们被问到:哪个,在标记行独立插入,会编译?
所以,我正在测试第一个答案 - return new Carpet<X>()
。有用。好吧,我的推理很顺利,如果我的返回类型为Carpet<? extends V>
,它必须返回扩展V
的内容。就在它写完之前X extends V
,以便完美,X
有效。
下一个答案 - return new Carpet<V>()
。嗯,这更简单,因为V
已经&#34;延伸&#34; V
,所以我可以回复。它确实有用。
下一步 - return new Carpet<A>()
。这不起作用,编译器大喊:
Type parameter 'A' is not within its bound; should extend 'B'
但是,我同意。它写在班级宣言V extends B
附近。所以,我知道我可以返回扩展V
的内容B
。肯定不是A
。
所以,我看到了下一个答案 - return new Carpet<B>()
。 Phew,简单,编译器只是说&#34;应该扩展B
,所以B
(就像V
之前的V
一样延伸Error:(6, 16) java: incompatible types
required: Carpet<? extends V>
found: Carpet<B>
&#34 ;)应该是完美的。但!它没有编译:
B
我不明白为什么。书中给出的解释是:
由于V的确切范围,使用具体类类型是非法的 不明。
但坦率地说,我仍然没有得到它。我不确定&#34;确切的范围&#34;在该上下文中,但编译器说,返回类型参数应该扩展V
。所以,他能够弄明白(像我一样)&#34;扩展B
&#34;是{&#34;延伸B
&#34;的东西。那么,为什么{{1}}不起作用?
请您提供更好的解释?
答案 0 :(得分:2)
V是地毯的通用类型。在实例化一个Carpet时,该类的用户选择具体的V类型。它可以是B,或C,或直接或间接扩展B的任何其他类:
Carpet<B> carpetOfB = new Carpet<B>();
或
Carpet<C> carpetOfC = new Carpet<C>();
或
Carpet<Plane> carpetOfPlane = new Carpet<Plane>();
无论用户选择V的具体类型(假设他选择了扩展C的Plane),该方法必须返回一个扩展为V的类型的地毯。因此,在这种情况下,此类型必须是Plane或者Plane的子类型。显然,B不符合条件,因为它不会扩展Plane。