下面的代码不会编译,它说该方法不适用于参数。有趣的是,如果我删除其中一个参数(无关紧要),那么它编译得很好。
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)
然后没关系。这里发生了什么?
答案 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
作为第二个参数:您可以传递不适合的Shape
和Collection<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 {
}
}