开发者

Using generics with wildcards does not allow using methods with generic as a parameter

开发者 https://www.devze.com 2023-01-06 16:20 出处:网络
If i declare a generic class as something like public class Driver<V extends Car> where Car is an interface.

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.

W开发者_C百科hy 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<?>).


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.


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

  • Angelika Langer's Java Generics FAQ
    • Which methods and fields are accessible/inaccessible through a reference variable of a wildcard parameterized type?

Related questions

  • How can I add to List<? extends Number> data structures?
0

精彩评论

暂无评论...
验证码 换一张
取 消