Вопрос:
Объект параметризованного класса при доступе из подкласса рассматривается как необобщенный. Как мне преодолеть это?
Подробности:
Рассмотрим базовый класс:
public class MyBaseClass {
protected List<Number> numbers = new ArrayList<Number>();
public MyBaseClass(){
//...
}
}
Теперь давайте расширим этот класс:
public class MyDerivedClass extends MyBaseClass {
public void addSomething() {
numbers.add(25.0f); //Warning about type-safety here
}
}
В производном классе объект чисел рассматривается как необработанный тип. Предупреждение:
Безопасность типов: метод add(Object) относится к необработанному типу List. Ссылки на общий тип List должны быть параметризованы.
Если я попытаюсь добавить параметр типа самостоятельно, я получу ошибку компиляции:
numbers.<Number>add(25.0f); //Error here
Я вижу ошибку:
Метод add(Number) типа List не является универсальным; его нельзя параметризовать аргументами
Однако, если я помещу оба класса в один и тот же исходный файл Java, эта проблема исчезнет. Во-первых, нет предупреждения. Это был образец для иллюстрации проблемы.
В моем реальном приложении я хочу иметь возможность получать элементы из List
в производном классе и выполнять над ними специфичные для класса операции без необходимости сначала приводить полученный объект к соответствующему типу.
Я подозреваю, что проблема связана со стиранием типа, но я не могу понять, как это обойти.
РЕДАКТИРОВАТЬ:
Я использую Eclipse 3.7.2 и Oracle JDK 1.6.0_30 на Fedora Core 16. Соответствие компилятора установлено на 1.6 с настройками соответствия по умолчанию. Как я уже упоминал, если я помещаю оба класса в один и тот же файл .java, я не вижу предупреждения. Видно, только если я помещаю их в разные файлы.
Я могу обойти это, определив все методы, которые непосредственно работают с объектом списка в родительском классе; и используя это из производного класса.
Но мне все еще любопытно, почему я вижу предупреждение. Вот обходной путь:
В MyBaseClass:
protected void addNumberToList(Number num){
numbers.add(num);
}
а затем в производном классе:
public void addSomething() {
addNumberToList(25.0f);
}
Точно так же все операции, которые напрямую манипулируют объектом List
, могут быть в базовом классе.