Использование шаблонов с подстановочными знаками не позволяет использовать методы с шаблонами в качестве параметра - PullRequest
1 голос
/ 12 июля 2010

Если я объявляю обобщенный класс как что-то вроде

public class Driver<V extends Car>

, где Car - это интерфейс.

Затем я использую это с чем-то вроде этого:

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

Я не хочу указывать конкретную реализацию автомобиля в качестве универсального.

Почему я не могу вызвать методы, реализованные в драйвере, который использует универсальный класс в качестве параметра?

Например, если у Driver есть метод, такой как

public void drive(V vehicle)

Это не позволяет мне вызывать это с моим экземпляром драйвера (Driver<?>).

Ответы [ 2 ]

4 голосов
/ 12 июля 2010

Поскольку компилятор не знает, какой тип аргумента driver.drive(? vehicle) примет. Стоит ли брать Шевроле, Хонду или какой-то другой тип?

Для получения более подробной информации вы можете найти Обобщающее руководство Гилада Брачи .

Какова цель вашего метода drive (). Нужно ли вводить параметр vehicle для определенного подтипа Car? Было бы более уместно для него просто принять Car?


Следующее было частью моего первоначального ответа, но обсуждение в комментариях доказало, что он был неверным. Я оставляю это здесь, чтобы комментарии не были осиротевшими.

Попробуйте объявить ваш метод следующим образом:

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

и посмотрите, будет ли это лучше для вас.

3 голосов
/ 12 июля 2010

Вопрос неопределенный, но я полагаю, что на этот отрывок из часто задаваемых вопросов по Generics Java от Angelika Langer есть ответ:

Какие методы и поля доступны / недоступны через ссылочную переменную параметризованного типа с подстановочными знаками?

Зависит от типа подстановочного знака.

Использование объекта через ссылочную переменную параметризованного типа с подстановочными знаками ограничено. Рассмотрим следующий класс:

Пример (универсального класса):

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

По существу, ? имеет меньше информации для универсальной системы типов, и поэтому для обеспечения безопасности типов определенные вызовы должны быть отклонены, поскольку они не безопасны.

A Box<?> может быть Box<Integer>, Box<String> или даже Box<Box<?>>. Таким образом, с учетом Box<?> box, box.put("xyz") должно быть отклонено.

Ссылки

Смежные вопросы

...