如果我将泛型类声明为类似
public class Driver<V extends Car>
其中Car是一个界面。
然后,我用这样的东西:
Driver<?> driver = new Driver<Chevrolet>();
我不想指定汽车的特定实现作为通用。
为什么我不能调用在使用泛型类作为参数的驱动程序中实现的方法?
例如,如果Driver有类似
的方法public void drive(V vehicle)
我不允许用我的驱动程序实例(Driver<?>
)来调用它。
答案 0 :(得分:4)
因为编译器不知道参数driver.drive(? vehicle)
将接受什么类型的参数。它应该采用雪佛兰,本田还是其他类型?
有关详情,您可能会发现Gilad Bracha's Generics Tutorial有帮助。
您的drive()方法的目的是什么?是否需要将vehicle
参数键入Car的特定子类型?简单地接受Car
?
以下是我原来答案的一部分,但评论中的讨论证明这是不正确的。我将它留在这里,所以评论不是孤立的。
尝试像这样声明你的方法:
public <T extends V> void drive(T vehicle)
并查看这是否适合您。
答案 1 :(得分:3)
这个问题很模糊,但我相信Angelika Langer的Java Generics常见问题解答摘录了它:
通过通配符参数化类型的引用变量可访问/不可访问哪些方法和字段?
这取决于通配符的种类。
通过通配符参数化类型的引用变量使用对象受到限制。考虑以下课程:
(通用类的)示例:
class Box<T> { private T t; public Box(T t) { this.t = t; } public void put(T t) { this.t = t;} public T take() { return t; } public boolean equalTo(Box<T> other) { return this.t.equals(other.t); } public Box<T> copy() { return new Box<T>(t); } }
当我们使用Box类型的通配符实例化的引用变量时 访问编译器所引用的对象的方法和字段 拒绝某些调用。
示例(通过通配符参数化类型访问):
class Test { public static void main(String[] args) { Box<?> box = new Box<String>("abc"); box.put("xyz"); // error box.put(null); // ok String s = box.take(); // error Object o = box.take(); // ok boolean equal = box.equalTo(box); // error equal = box.equalTo(new Box<String>("abc")); // error Box<?> box1 = box.copy(); // ok Box<String> box2 = box.copy(); // error } }
基本上?
对于泛型类型系统的信息较少,因此为了强制执行类型安全,必须拒绝某些调用,因为它们不是类型安全的。
Box<?>
可能是Box<Integer>
,Box<String>
,甚至是Box<Box<?>>
。因此,如果Box<?> box
,则必须拒绝box.put("xyz")
。