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

时间:2012-01-22 15:15:30

标签: java generics bounded-wildcard

以下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)

5 个答案:

答案 0 :(得分:3)

您已将A类的通用参数定义为一件事,但之后尝试在构造函数中以不兼容的方式使用它(<T extends Shape><? extends Shape>不同。获取代码编译将其更改为始终使用已定义的泛型参数:

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

顺便说一句,您的代码不会生成您在问题中显示的错误消息。相反,它会更像是这样:

  

方法绘制(捕获#1-of?extends GenericsHell.Shape)在类型中   GenericsHell.ShapeHelper是   不适用于参数(T)

答案 1 :(得分:2)

  

方法draw(捕获#1-of?extends GenericsHell.Shape)类型为GenericsHell.ShapeHelper&lt; capture#1-of?扩展GenericsHell.Shape&gt;不适用于参数(T)

问题在于,在声明中,shape的类型为T,但是您要求的ShapeHelper类型为&lt;?扩展形状&gt;这意味着可以将一个ShapeHelper作为参数传递,其中S和T是不同的。

然后,您可以致电helper<S>.draw(shape<T>);,这是没有意义的。

此方法的正确实现是:

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

确保形状和形状辅助器具有兼容类型。

答案 2 :(得分:1)

看到您对A的来电非常重要。但似乎你做了像A<Integer>这样的事情。但T必须根据您的班级声明延长Shape,而Integer则不然。因此,要么将<? extends Shape>更改为<T>,要么提供ShapeA的类型

答案 3 :(得分:0)

请改为尝试:

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

答案 4 :(得分:0)

记住PECS(制作人extends,消费者super)。

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