Можно ли избежать непроверенных предупреждений при переопределении метода с необработанными параметрами типа? - PullRequest
16 голосов
/ 28 октября 2008

Я расширяю класс, определенный в библиотеке, который я не могу изменить:

public class Parent
{
    public void init(Map properties) { ... }
}

Если я определяю класс 'Child', расширяющий Parent, и использую Java 6 с обобщениями, каков наилучший способ переопределить метод init без получения непроверенных предупреждений?

public class Child extends Parent
{
    // warning: Map is a raw type. References to generic type Map<K,V> should be parameterized
    public void init(Map properties) { }
}

Если я добавлю общие параметры, я получу:

   // error: The method init(Map<Object,Object>) of type Child has the same erasure as init(Map) of type Parent but does not override it
   public void init(Map<Object,Object>) { ... }
   // same error
   public void init(Map<? extends Object,? extends Object>) { ... }
   // same error
   public void init(Map<?,?>) { ... }

Эта ошибка возникает независимо от того, использую ли я определенный тип, ограниченный подстановочный знак или неограниченный подстановочный знак. Есть ли правильный или идиоматический способ переопределить неуниверсальный метод без предупреждений и без использования @SuppressWarnings («unchecked»)?

Ответы [ 4 ]

13 голосов
/ 28 октября 2008

Да, вы должны объявить переопределяющий метод с той же сигнатурой, что и в родительском классе, без добавления общей информации.

Я думаю, что вам лучше всего добавить аннотацию @SuppressWarnings("unchecked") к параметру raw-type, а не к методу, чтобы вы не подавили предупреждения общего характера, которые вы могли бы иметь в своем коде.

3 голосов
/ 28 октября 2008

Краткий ответ: нет способа сделать это.

Неудовлетворительный ответ: отключите (конкретные) предупреждения в вашей IDE / build.xml.

Если вы не можете изменить библиотеку, увы, вы должны придерживаться неуниверсальных методов.

Проблема в том, что, несмотря на то, что после стирания типа оба init () имеют одну и ту же сигнатуру, на самом деле они могут быть разными методами или одинаковыми (*). Компилятор не может сказать, должен ли он переопределить или перегрузить, поэтому он запрещен.

(*) Предположим, что разработчик библиотеки имел в виду init (Map ). Теперь вы реализуете init (Map ). Это перегрузка, и в vtable класса Child должно существовать два метода.

Но что, если разработчик библиотеки имел в виду init (Map )? Затем он переопределяет, и ваш метод должен заменить оригинальный init в классе Child, и в vtable of Child будет только один метод.

P.S. Я ненавижу, как Generics реализован в Java: - (

2 голосов
/ 28 апреля 2011

Я думаю, что ответ выше означал бы вместо этого сказать @SuppressWarnings ("rawtypes").

0 голосов
/ 28 октября 2008

Вы должны объявить метод с той же сигнатурой, что и у родителя, и поэтому вы получите предупреждения при компиляции. Вы можете подавить их с помощью @SuppressWarnings («unchecked»)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...