通用方法仅使用一个参数进行编译

时间:2015-06-22 13:32:04

标签: java generics

下面的代码不会编译,它说该方法不适用于参数。有趣的是,如果我删除其中一个参数(无关紧要),那么它编译得很好。

public class Test1 {
    static Collection<? extends Shape> someColl = new ArrayList<Shape>();

    public static void main(String args[]) {
        new Test1();
    }

    public static void Main(String[] args) {
        addShape(someColl, new Circle()); //compilation error
    }

    static <T extends Shape> void addShape(Collection<T> shapes, T shape) {
        shapes.add(shape);
    }

    abstract class Shape {

    }

    class Rect extends Shape{

    }

    class Circle extends Shape {

    }
}

如果我删除其中一个方法参数并将其更改为

addShape(someColl)

static <T extends Shape> void addShape(Collection<T> shapes)

或将其更改为

addShape(new Circle())

static <T extends Shape> void addShape(T shape)

然后没关系。这里发生了什么?

2 个答案:

答案 0 :(得分:1)

问题在于,当您致电addShape(someColl, new Circle());时,T有两种不同的定义

    来自? extends Shape
  • Collection<? extends Shape> someColl 来自第二个参数
  • Circle

该调用的另一个问题是T需要是第二个参数的具体类型,即您不能将其定义为? extends Shape shape,因为推断{来自T的{​​1}}。

被称为Collection<? extends Shape>的方法建议您将作为第二个参数传递的形状添加到集合中。但是,由于编译器无法知道是否允许使用addXxxx或任何其他形状类型,因此无法使用Collection<? extends Shape>

假设您将方法更改为接受Circle作为第二个参数:您可以传递不适合的ShapeCollection<Rect>

在您的情况下,最好的选择是将Circle的定义更改为someColl,因为无论如何,您使用Collection<Shape>做了什么。然后,编译器会将ArrayList<Shape>推断为T,并且调用应该编译。

答案 1 :(得分:0)

也许你只需要使用一个接口就可以在同一个集合中添加Rects和Cicles。如果这是你想要做的事情:

public class Test1 {
   static Collection<Shape> someColl = new ArrayList<Shape>();

   public static void main(String[] args) {
       Test1 t = new Test1();
       Circle c = t.new Circle();
       Rect r = t.new Rect();
       addShape(someColl, c);
       addShape(someColl, r);
   }

   static boolean addShape(Collection<Shape> someColl2, Shape shape) {
       return someColl2.add(shape);
   }

   interface Shape {

   }

   abstract class AbstractShape {

   }

   class Rect extends AbstractShape implements Shape{

   }

   class Circle extends AbstractShape implements Shape {

   }
}