Generic (Java)

Материал из Циклопедии
Перейти к навигации Перейти к поиску

Generic в Java — средство выражения ограничений поведения классов или методов для исходно неизвестных типов. Является одним из механизмов, поддерживающих парадигму обобщённого программирования.

Предпосылки[править]

До Java 1.5 чтобы определить класс, в котором допустима работы с различными типами данных (например, коллекцию), следовало объявлять эти данные как Object. Соответственно, на программиста возлагалась задача явно контролировать, какому же типу данных принадлежат используемые объекты. Это требовало постоянного использования проверок instanceOf и явного приведения типа, которые, как известно, не являются безопасными и могут в выбрасывать ClassCastException.

Решением этой проблемы стало введение механизма generic в Java 1.5.

Использование generic[править]

Объявить с применением generic можно:

  • Класс и интерфейс (после имени класса/интерфейса в угловых скобках указываются перечисленные через запятую generic);
   public class MyMap<K, V>
  • Метод (перед возвращаемым типом в угловых скобках указываются generic).
   public <T> void fill(List<T> list, T val)

При создании объекта generic-класса следует указать, какие типы данных использовать. При вызове параметризованного метода указать типы данных можно следующим образом:

    <Integer>swap(ints, 1, 3);

Следует отметить, что в целях совместимости с ранним версиями Java при использовании generic допустимо не указывать тип данных (использовать так называемые raw types), однако это не рекомендуется, так как возвращает все те проблемы, которые призван решить этот механизм.

Поддержка generic[править]

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

  • Отсутствует возможность определить generic примитивным типом;
  • Невозможно создать объект типа generic (недопустимы конструкции вида E e = new E());
  • В параметризованном классе запрещено использовать generic в статическом контексте;
  • Невозможно использовать параметризованные классы как правый операнд оператора instanceof;
  • Невозможно создать массив параметризованного типа;
  • Невозможно указать generic в секциях catch и throw (однако допустимо в секции throws);
  • Невозможно перегружать методы таким образом, что после стирания типов сигнатуры обоих методов совпадут.

Ограничения на допустимые типы[править]

Java предоставляет возможность ограничить допустимые generic-типы. При объявлении параметризованного класса или метода можно использовать конструкции вида <T extends Phone>. В этом случае качестве T может подставить только Phone и его наследников. Можно указать один класс и несколько интерфейсов, разделяя их оператором &.

Кроме того, механизм Generic предоставляет возможность оперировать с масками (wildcard) — вместо типа использовать вопросительный знак. Они используются тогда, когда нужно абстрагироваться от конкретных аргументов типа, и позволяют использовать его там, где не требуется знать конкретные типы параметров. Использовать можно маски без ограничений (например, Map<key, ?>, а также с ограничениями List<? extends MyClass>, List<? super MyClass>).

Ссылки[править]