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

发布于 2024-09-08 18:25:12 字数 428 浏览 5 评论 0 原文

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

public class Driver<V extends Car>

Car 是接口的类。

然后,我将它与这样的东西一起使用:

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

我不想将 car 的特定实现指定为通用。

为什么我无法调用驱动程序中以泛型类作为参数实现的方法?

例如,如果 Driver 有一个类似

public void drive(V vehicle)

It 的方法,则不允许我使用我的驱动程序实例调用该方法 (Driver)。

If i declare a generic class as something like

public class Driver<V extends Car>

where Car is an interface.

Then, I use it with something like this:

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

I don't want to specify a specific implementation of car as the generic.

Why is it that I cannot call methods implemented in driver that uses the generic class as the parameter?

For example if Driver has a method like

public void drive(V vehicle)

It does not allow me to call that with my instance of driver (Driver<?>).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

自此以后,行同陌路 2024-09-15 18:25:12

因为编译器不知道driver.drive(?vehicle)将接受什么类型的参数。应该选择雪佛兰、本田还是其他类型的车?

有关更多详细信息,您可能会发现Gilad Bracha 的泛型教程很有帮助。

你的drive()方法的目的是什么? vehicle 参数是否需要输入 Car 的特定子类型?简单地接受汽车会更合适吗?


以下是我原来答案的一部分,但评论中的讨论证明这是不正确的。我把它留在这里,这样评论就不会被孤立。

尝试像这样声明你的方法:

public <T extends V> void drive(T vehicle)

看看它是否更适合你。

Because the compiler doesn't know what type of argument driver.drive(? vehicle) will accept. Should it take a Chevrolet, a Honda, or some other type?

For more details you might find Gilad Bracha's Generics Tutorial helpful.

What is the purpose of your drive() method. Does the vehicle parameter need to be typed to the specific subtype of Car? Would it be more appropriate for it to simply accept a Car?


The following was part of my original answer, but discussion in the comments proved that it was incorrect. I'm leaving it here so the comments aren't orphaned.

Try declaring your method like this:

public <T extends V> void drive(T vehicle)

and see if that works better for you.

凹づ凸ル 2024-09-15 18:25:12

这个问题很模糊,但我相信 Angelika Langer 的 Java 泛型常见问题解答的摘录可以回答这个问题:

哪些方法和字段可以通过通配符参数化类型的引用变量访问/不可访问?

这取决于通配符的类型。

通过通配符参数化类型的引用变量使用对象受到限制。考虑下面的类:

示例(泛型类):

class Box; {
  私人 T t;
  公共框(T t){ this.t = t; }
  public void put(T t) { this.t = t;}
  公共 T take() { 返回 t; }
  公共布尔 equalTo(Box other) {
     返回 this.t.equals(other.t);
  }
  公共信箱复制() {
     返回新框(t);
  }
} 

当我们使用 Box 类型的通配符实例化的引用变量时
编译器将访问引用对象的方法和字段
拒绝某些调用。

示例(通过通配符参数化类型进行访问):

类测试{
  公共静态无效主(字符串[] args){
    盒子 box = new Box("abc");

    盒子.put("xyz"); // 错误
    盒子.put(null); // 好的

    String s = box.take(); // 错误
    对象 o = box.take(); // 好的

    布尔等于 = box.equalTo(box); // 错误
    equal = box.equalTo(new Box("abc")); // 错误

    盒子 box1 = box.copy(); // 好的
    框<字符串> box2 = box.copy(); // 错误
  }
}

本质上 ? 对于泛型类型系统的信息较少,因此为了强制执行类型安全,必须拒绝某些调用,因为它们不是类型安全的。

Box 可以是 BoxBox,甚至是 Box>。因此给出一个 Box; boxbox.put("xyz") 必须被拒绝。

参考文献

相关问题

The question is vague, but I believe this excerpt from Angelika Langer's Java Generics FAQ answers it:

Which methods and fields are accessible/inaccessible through a reference variable of a wildcard parameterized type?

It depends on the kind of wildcard.

Using an object through a reference variable of a wildcard parameterized type is restricted. Consider the following class:

Example (of a generic class):

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);
  }
} 

When we use a reference variable of a wildcard instantiation of type Box to
access methods and fields of the referenced object the compiler would
reject certain invocations.

Example (of access through a wildcard parameterized type):

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
  }
}

Essentially ? has less information for the generic type system, and thus to enforce typesafety certain invokations must be rejected, because they're not typesafe.

A Box<?> may be a Box<Integer>, a Box<String>, or even a Box<Box<?>>. Thus given a Box<?> box, box.put("xyz") must be rejected.

References

Related questions

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文