0

下面有什么问题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)

4

5 回答 5

3

您将 Class A 的泛型参数定义为一件事,但随后尝试在构造函数中以不兼容的方式使用它(<T extends Shape><? extends Shape>.

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

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

GenericsHell.ShapeHelper 类型中的方法 draw(capture#1-of ? extends GenericsHell.Shape) 不适用于参数 (T)

于 2012-01-22T15:18:10.790 回答
2

类型 GenericsHell.ShapeHelper<capture#1-of 中的方法 draw(capture#1-of ? extends GenericsHell.Shape) extends GenericsHell.Shape> 不适用于参数 (T)

问题是,在您的声明中,shape 的类型是 T,但您请求的 ShapeHelper 类型为 <? extends Shape> 这意味着可以将 S 和 T 不同的 ShapeHelper 作为参数传递。

然后你会打电话给helper<S>.draw(shape<T>);这没有意义。

此方法的正确实现是:

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

这确保了形状和形状助手是兼容的类型。

于 2012-01-22T15:27:18.090 回答
1

看到你的电话很重要A。但似乎你做了类似的事情A<Integer>。但T必须Shape根据您的类声明进行扩展.. 而Integer不是。因此,要么更改<? extends Shape>为,要么提供<T>一个类型ShapeA

于 2012-01-22T15:20:48.457 回答
0

试试这个:

class A<T extends Shape> {
    A(T shape, ShapeHelper<T> helper) {
        helper.draw(shape);
    }
}
于 2012-01-22T15:24:03.220 回答
0

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

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

于 2012-01-22T22:45:18.400 回答