До появления Java SE 5.0 был написан огромный объем кода Java. Если бы обобщенные классы не могли взаимодействовать с этим кодом, они не получили бы широкого распространения. К счастью, достаточно просто использовать обобщенные классы вместе с их «сырыми» эквивалентами из унаследованного API.
Рассмотрим конкретный пример. Чтобы установить метки JSlider, вы используете метод:
1 |
void setLabelTable(Directory table) |
В Java SE 5.0 классы Dictionary и Hashtable превратились в обобщенные классы. Поэтому можно сформировать Dictionary<Integer, Component> вместо использования «сырого» Dictionary. Однако когда вы передаете объект Dictionary<Integer, Component> методу setLabelTable, компилятор выдает предупреждение:
1 2 |
Directory<Integer, Component> labelTable = . . .; slider.setLabelTable(labelTable); // предупреждение |
В конце концов, компилятор не знает о том, что setLabelTable() может делать с объектом Dictionary. Этот метод может заменить все ключи строками. Это нарушит гарантию того, что ключи имеют тип Integer, и тогда будущие операции могут вызвать исключение приведения.
С этим предупреждением мало что можно сделать, кроме как обдумать его и спросить себя, что, скорее всего, JSlider собирается делать с объектом Dictionary? В нашем случае вполне ясно, что JSlider только читает информацию, так что мы можем проигнорировать предупреждение.
Теперь рассмотрим противоположный случай, когда вы получаете объект «сырого» типа от унаследованного класса. Вы можете присвоить его переменной параметризованного типа, но конечно, при этом получите предупреждение. Например:
1 |
Dictionary<Integer, Components> labelTable = slider.getLabelTable(); // предупреждение |
Все хорошо — просмотрите предупреждение и убедитесь, что таблица меток действительно содержит объекты Integer и Component. Конечно, абсолютной гарантии нет. Злоумышленник может инсталлировать другой Dictionary и JSlider. Но, опять-таки, эта ситуация на хуже той, что была до версии Java SE 5.0. В худшем случае ваша программа сгенерирует исключение.
После того, как вы обратили внимание на предупреждение, вы можете использовать аннотацию для того, чтобы оно исчезло. Аннотацию следует поместить перед методом, чей код генерирует предупреждение, как показано ниже:
1 2 |
@SuppressWarnings("unchecked") public void configureSlider() { . . . } |
К сожалению, эта аннотация отключает проверку всего кода внутри метода. Будет хорошей идеей изолировать потенциально небезопасный код в отдельных методах, чтобы его можно было легко просмотреть.
Hashtable — конкретный подкласс абстрактного класса Dictionary. И Dictionary, и Hashtable объявлены устаревшими, с тех пор как в Java SE 1.2 для них появилась замена в виде интерфейса Map и класс HashMap. Несмотря на это, упомянутые устаревшие классы до сих пор живут и здравствуют. В конце концов, класс JSlider был добавлен только в Java SE 1.3. Знали ли его разработчики о классе Map в то время? Можно ли рассчитывать, что они адаптируют его к обобщенным классам в будущем? В принципе, подобное всегда происходит с унаследованным кодом.
Вам нужны модные сумки для ваших планшетов? Лучшие всего вам подойдут сумки из Италии. Качество, ну просто сногсшибательная.