Можно ли избежать непроверенных предупреждений при переопределении метода с параметрами необработанного типа?

StackOverflow https://stackoverflow.com/questions/241539

Вопрос

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

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")?

Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

Но что, если разработчик библиотеки имел в виду init(Map<String,String>)?Тогда это переопределяет, и ваш метод должен заменять исходный init в классе Child, и в виртуальной таблице Child будет только один метод.

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top