2008-10-27 7 views
14

Я простирающийся класс, определенный в библиотеке, которую я не могу изменить:Можно ли избежать отмеченных предупреждений при переопределении метода с параметрами сырого типа?

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

Если я определяю класс «ребенок», который расширяет 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»)?

ответ

12

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

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

+0

@SuppressWarnings определенно ваш лучший выбор здесь. Отстой, но это то, что происходит, когда вы пытаетесь заставить generics в библиотеку, которая их не использует. – 2008-10-28 02:52:56

2

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

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

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

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

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

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

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

+0

Не могли бы вы объяснить, почему методы с одинаковой (стираемой) сигнатурой могут быть разными методами для компилятора? Компилятор не знает, что разработчик _meant_ при кодировании ... ;-) – nrainer 2015-05-28 08:34:44

0

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

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

2

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

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

  • Нет связанных вопросов^_^