Обобщения в Java – часть 2

ОГЛАВЛЕНИЕ

В следующей части будут рассмотрены проблемы со смешением обобщенного и необобщенного кода и проблемы с преобразованием необобщенного устаревшего кода в обобщения.

Непроверенное предупреждение

Компилятор Java предупреждает, если не может проверить безопасность типов. Это происходит при смешении обобщенного и необобщенного кода (это плохая идея). Разработка приложений без проверки таких предупреждений является риском. Лучше рассматривать предупреждения как ошибки.
Рассмотрите следующий пример:

public class Test
{
    public static void foo1(Collection c)
    {
    }

    public static void foo2(Collection<Integer> c)
    {
    }

    public static void main(String[] args)
    {
        Collection<Integer> coll = new ArrayList<Integer>();
        foo1(coll);

        ArrayList lst = new ArrayList();
        foo2(lst);
    }
}

Имеется метод foo1, принимающий традиционный Collection(коллекция) в качестве параметра. Метод foo2, напротив, принимает обобщенную версию Collection. Объект традиционного ArrayList отправляется методу foo2. Поскольку ArrayList может содержать объекты разных типов, внутри метода foo2, компилятор не в состоянии гарантировать, что Collection<Integer> будет содержать только экземпляры Integer. В данном случае компилятор выдает предупреждение, показанное ниже:

Предупреждение: строка (22) [не проверено] обнаружено непроверенное преобразование: 
          java.util.ArrayList требуется:
java.util.Collection<java.lang.Integer>

Хотя получить это предупреждение лучше, чем не быть предупрежденным о потенциальной проблеме, было бы лучше, если бы это была ошибка вместо предупреждения. Используйте флаг компиляции – Xlint, чтобы точно не упустить это предупреждение.

Есть еще одна проблема. В методе main отправляется обобщенный Collection из Integer методу foo1. Хотя компилятор не жалуется на это, это опасно. Что если внутри метода foo1 в коллекцию добавляются объекты типов, отличных от Integer? Это нарушит безопасность типов.

Возникает вопрос, почему компилятор разрешил рассматривать обобщенный тип как традиционный тип. Причина в том, что на уровне байтового кода нет понятия обобщений. Подробно это описано в разделе “Реализация обобщений”.

Ограничения

В использовании обобщений есть ряд ограничений. Нельзя создать массив обобщенных коллекций. Любой массив коллекций шаблонов разрешен, но является опасным с позиции безопасности типов. Нельзя создать обобщение элементарного типа. Например, ArrayList<int> запрещен. Нельзя создать параметризованные статические поля внутри обобщенного класса или иметь статические методы с параметризованными типами в качестве параметров. Например, рассмотрите следующее:

class MyClass<T>
{
    private Collection<T> myCol1; // нормально
    private static Collection<T> myCol2; // ошибка
}

Внутри обобщенного класса нельзя создать экземпляр объекта или массива объектов параметризованного типа. Например, если имеется обобщенный класс MyClass<T> внутри метода этого класса, нельзя написать:

new T();
или

new T[10];

Можно сгенерировать исключение обобщенного типа; однако в блоке catch придется использовать конкретный тип, вместо обобщенного.

Можно унаследовать класс от другого обобщенного класса; но нельзя унаследовать от параметрического типа. Например, тогда как:

class MyClass2<T> extends MyClass<T>
{
}

нормально,

class MyClass2<T> extends T
{
}

нет.

Запрещено наследовать от двух экземпляров одного и того же обобщенного типа. Например, тогда как:

class MyList implements MyCollection<Integer>
{
    //...
}

нормально,

class MyList implements MyCollection<Integer>, MyCollection<Double>
{
    //...
}

нет.

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

Читайте также:
  • Обобщения в Java: часть 1
    Аннотация Java 5 (JDK 1.5) ввел принцип обобщений или параметризованных типов. Данная статья знакомит с принципами обобщений и показывает примеры их использования. В части II рассмотрено, как обобщения на самом деле реализованы в Java, и несколько проблем с применением обобщений. Проблема безопа...
  • Введение в программирование Java GUI
    Введение Данная статья рассчитана на людей, совсем не имеющих или имеющих мало опыта в программировании Java GUI. По сути, эта статья делает упор на иерархической структуре, основывающейся на кадре и идущей в панель содержимого. В центре внимания находится виджет кнопки (управляющий элемент в .NE...
  • JSP – библиотека пользовательских тегов JSTL
    Пользовательские теги JSP Пользовательские теги JSP предоставляют стандартный механизм для разделения представления и бизнес-логики на динамической веб-странице, позволяя разработчикам страниц сосредоточиться на представлении, тогда как разработчики приложения программируют серверную часть. Они я...
  • Как вызвать веб-сервис Java в ASP.net с помощью C#
    Скачать Code.zip - 34.24 Кб Оглавление Вводная информация Определение Свойства веб-сервисов Базовые компоненты Способность к взаимодействию веб-сервисов Создание веб-сервиса Java Создать проект веб-приложения Добавить веб-сервис в проект Добавить операции в веб-сервис Реализация...
  • Внедрение содержимого WPF в приложение Java
    ·         Скачать демонстрационный проект - 130.98 Кб ·         Скачать исходный код - 37.93 Кб Введение Это очередная статья об объединении Java/.NET. Вводные сведения Здесь дается пример кода для внедрения компонентов .NET GUI в Java GUI. Если читатель не знаком с объектно-ориентированным...