下面的Class A
有什么问题,不允许它编译?
public class GenericsHell {
interface Shape{}
interface Circle extends Shape {}
interface ShapeHelper<T extends Shape> {
void draw(T shape);
}
class A<T extends Shape> {
A(T shape, ShapeHelper<? extends Shape> helper) {
helper.draw(shape); // Issues not-applicable argument error
}
}
class B {
B(Circle circle, ShapeHelper<Circle> helper) {
helper.draw(circle);
}
}
}
Eclipse给出以下错误:
The method draw(capture#1-of ? extends Shape) in the type ShapeHelper<capture#1-of ? extends Shape> is not applicable for the arguments (T)
您将类A的泛型参数定义为一回事,但随后试图在构造函数中以不兼容的方式使用它(<T extends Shape>
与<? extends Shape>
不同。要编译代码,请将其更改为一致使用已定义的泛型参数:
class A<T extends Shape> {
public A(T shape, ShapeHelper<T> helper) {
helper.draw(shape);
}
}
顺便说一句,您的代码不会生成您在问题中显示的错误消息。相反,它会更像这样:
类型中的方法draw(capture#1-of?extended GenericsHell.Shape)GenericsHell.ShapeHelper是不适用于自变量(T)
在类型GenericsHell.ShapeHelper<捕获第1个?extended GenericsHell.Shape>不适用于参数(T)
问题是,在您的声明中,形状是T类型的,但您请求类型<?的ShapeHelper;?扩展了Shape>,这意味着可以传递一个ShapeHelper作为参数,其中S和T是不同的。
然后您会调用helper<S>.draw(shape<T>);
,这是没有意义的。
这种方法的正确实现是:
class A<T extends Shape> {
A(T shape, ShapeHelper<T> helper) {
helper.draw(shape);
}
}
这样可以确保形状和形状辅助对象的类型是兼容的。
查看您对A
的调用非常重要。但你似乎做了类似A<Integer>
的事情。但是T
必须根据您的类声明来扩展Shape
。。而CCD_ 10没有。因此,要么将<? extends Shape>
更改为<T>
,要么提供一个类型,即Shape
到A
试试这个:
class A<T extends Shape> {
A(T shape, ShapeHelper<T> helper) {
helper.draw(shape);
}
}
记住PECS(生产者extends
,消费者super
)。
helper
是一个消费者(您将某些东西传递给它),因此它不能是extends
。也许它可能是super
,但我不知道这在这种情况下是否有意义