Метод с типизированным списком и наследованием

У меня проблемы с методом, имеющим типизированный параметр List, унаследованный от другого (типизированного) класса.

Давайте будем простыми:

public class B<T> {
  public void test(List<Integer> i) {
  }
}

Класс B имеет бесполезный общий T, а test () хочет целочисленный список.

Теперь, если я это сделаю:

public class A extends B {
  // don't compile
  @Override
  public void test(List<Integer> i) {
  }
}

Я получаю ошибку «Тест метода (список) типа A должен переопределить или реализовать метод супертипа», чего не должно происходить.

Но удаление типа списка работает ... хотя это не зависит от универсального класса.

public class A extends B {
  // compile
  @Override
  public void test(List i) {

А также определение бесполезного универсального нижеприведенного для использования типизированного списка

public class A extends B<String> {
  // compile
  @Override
  public void test(List<Integer> i) {

Итак, я не понимаю, общий тип B не должен влиять на тип списка test (). Кто-нибудь имеет представление о том, что происходит?

Спасибо


person PomPom    schedule 28.06.2012    source источник
comment
Я считаю, что ваш ответ находится здесь.   -  person nobeh    schedule 28.06.2012
comment
Обычно [заглавная V] Void используется для общих параметров, которые вы не хотите использовать. Например, который использует java.security.PreivilegedAction без возврата значения (return null - это единственная действительная ссылка Void).   -  person Tom Hawtin - tackline    schedule 28.06.2012


Ответы (2)


Вы расширяете необработанный тип B, а не общий. Необработанный фактически имеет не test(List<Integer> i) метод, а test(List) метод.

Если вы переключаетесь на необработанные типы, все универсальные шаблоны заменяются необработанными, независимо от того, был ли их тип заполнен или нет.

Чтобы сделать это правильно, сделайте

 public class A<T> extends B<T>

Это будет использовать универсальный тип B<T>, который включает метод, который вы хотите переопределить.

person Joeri Hendrickx    schedule 28.06.2012
comment
Спасибо. Это не совсем логично, поскольку мы не используем T, но у дженериков java есть некоторые недостатки дизайна, с которыми мы должны бороться. - person PomPom; 29.06.2012

Когда вы удаляете использование класса без универсальных шаблонов (и используете его в исходном виде), все универсальные шаблоны из методов класса забываются.

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

Этот:

class T<G> {
   public void test(G g);
}

в таком случае:

class A extends T {
}

будет выглядеть так:

class T {
   public void test(Object g);
}

Это была java-головоломка, представленная на Google IO 2011, вы можете посмотреть видео здесь

person Francisco Spaeth    schedule 28.06.2012
comment
Настоящая проблема в том, что я использовал не G, а конкретный класс. В любом случае я получил свой ответ - person PomPom; 29.06.2012