不能从有界通配符引用引用泛型类型



下面的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>,要么提供一个类型,即ShapeA

试试这个:

class A<T extends Shape> {
    A(T shape, ShapeHelper<T> helper) {
        helper.draw(shape);
    }
}

记住PECS(生产者extends,消费者super)。

helper是一个消费者(您将某些东西传递给它),因此它不能是extends。也许它可能是super,但我不知道这在这种情况下是否有意义

最新更新