将泛型与通配符一起使用不允许使用泛型作为参数的方法

时间:2010-07-12 12:51:21

标签: java generics wildcard compiler-errors

如果我将泛型类声明为类似

public class Driver<V extends Car>

其中Car是一个界面。

然后,我用这样的东西:

Driver<?> driver = new Driver<Chevrolet>();

我不想指定汽车的特定实现作为通用。

为什么我不能调用在使用泛型类作为参数的驱动程序中实现的方法?

例如,如果Driver有类似

的方法
public void drive(V vehicle)

我不允许用我的驱动程序实例(Driver<?>)来调用它。

2 个答案:

答案 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")

参考

相关问题