Дженерики Flashcards

1
Q

Что такое дженерики?

A

Дженерики (обобщения) — это особые средства языка Java для использования обобщенных типов и методов.
Это вид параметрического полиморфизма.
Обобщенные типы и методы отличаются от обычных тем, что имеют типизированные параметры.
Существует 4 различных способа применения:
Типовой класс: Класс называется дженериком, если он объявляет одну или несколько переменных типа.
Интерфейс: то же с интерфейсом
Метод: отличаются тем что информация о области действия или типе находится только внутри метода
Конструктор: дженерики могут указываться в атрибутах

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

Примером использования обобщенных типов может служить Java Collection Framework. Так, класс LinkedList - типичный обобщенный тип. Он содержит параметр E, который представляет тип элементов, которые будут храниться в коллекции. Создание объектов обобщенных типов происходит посредством замены параметризированных типов реальными типами данных. Вместо того, чтобы просто использовать LinkedList, ничего не говоря о типе элемента в списке, предлагается использовать точное указание типа LinkedList, LinkedList и т.п.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Для чего нужны дженерики?

A
  • позволяет писать код / использовать библиотечные методы, которые являются типобезопасными, т. е. List гарантированно является списком строк.
  • компилятор может проверить во время компиляции, что ограничения типа не нарушаются во время выполнения. Поскольку программа компилируется без предупреждений, мы можем с уверенностью утверждать, что она не будет вызывать ClassCastException во время выполнения.
  • позволяет писать код, который применим ко многим типам с одинаковым базовым поведением
  • основным преимуществом, как указывает Митчел, является сильная типизация без необходимости определения нескольких классов.
  • отсутствие необходимости в типизации является одним из самых больших преимуществ Java generics, так как он будет выполнять проверку типов во время компиляции. Это уменьшит возможность ClassCastExceptions, которые могут быть брошены во время выполнения и могут привести к более надежному коду.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Что такое сырые типы (raw type)?

A

Сырой тип (raw type) — это имя обобщённого класса или интерфейса без аргументов типа (type arguments).

Например, параметризованный тип создаётся так:
Lair goblinLair = new Lair<>();
Если убрать аргументы типа, то будет создан сырой тип:
Lair lair = new Lair();
Поэтому Lair — это сырой тип обобщённого типа Lair . Однако необобщённый класс или интерфейс НЕ являются сырыми типами.

Для совместимости со старым кодом допустимо присваивать параметризованный тип своему собственному сырому типу:
Lair goblinLair = new Lair<>();
Lair lair = goblinLair; // OK
Но если вы попытаетесь присвоить параметризованному типу сырой тип, то будет предупреждение (warning):
Lair lair = new Lair();
Lair goblinLair = lair; // warning

Сообщения об ошибках “unchecked”
Как упоминалось выше, при использовании сырого типа вы можете столкнуться с предупреждениями вида: Термин “unchecked” означает непроверенные, то есть компилятор не имеет достаточного количества информации для обеспечения безопасности типов.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Что такое вайлдкарды?

A

Проблема: Между объектом и коллекцией объектов есть важное различие. Если класс B является наследником класса А, то Collection<b> при этом — не наследник Collection<a>.
List strings = new ArrayList();
// ошибка компиляции!
List objects = strings;
Таким образом, мы лишились гарантии того, что в нашей коллекции находятся только указанные в дженерике объекты String. То есть, мы потеряли главное преимущество дженериков — типобезопасность.</a></b>

Первый из нескольких типов wildcard — “extends” (другое название — Upper Bounded Wildcards). Это значит, что метод принимает на вход коллекцию объектов класса Animal либо объектов любого класса-наследника Animal (? extends Animal)

“super” (другое название — Lower Bounded Wildcards). Конструкция говорит компилятору, что метод iterateAnimals() может принимать на вход коллекцию объектов класса Cat либо любого другого класса-предка Cat.
</a></b>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Как Generics работает в Java? Что такое стирание типа?

A

дженерики появились только в версии языка Java 5. К моменту ее выхода программисты успели написать кучу кода с использованием Raw Types, и чтобы он не перестал работать, возможность создания и работы Raw Types в Java сохранилась.

Однако эта проблема оказалась гораздо обширнее.

Java-код, как ты знаешь, преобразуется в специальный байт-код, который потом выполняется виртуальной машиной Java.

И если бы в процессе перевода мы помещали в байт-код информацию о типах-параметрах, это сломало бы весь ранее написанный код, ведь до Java 5 никаких типов-параметров не существовало!

При работе с дженериками есть одна очень важная особенность, о которой необходимо помнить. Она называется “стирание типов” (type erasure).

Ее суть заключается в том, что внутри класса не хранится никакой информации о его типе-параметре.

Эта информация доступна только на этапе компиляции и стирается (становится недоступной) в runtime.

Если ты попытаешься положить объект не того типа в свой List, компилятор выдаст ошибку. Этого как раз и добивались создатели языка, создавая дженерики — проверки на этапе компиляции.

Но когда весь написанный тобой Java-код превратится в байт-код, в нем не будет информации о типах-параметрах.

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Расскажите про принцип PECS

A

PECS — Producer Extends, Consumer Super. Его суть:

Коллекции с wildcards и ключевым словом extends — это producers (производители, генераторы), они лишь предоставляют данные.
Коллекции с wildcards и ключевым словом super — это consumers (потребители), они принимают данные, но не отдают их.

Чиать: Объекты SomeType и всех его супертипов
Писать: Только null

Читать: Объекты типа Object Писать: Объекты типа SomeType и всех его подтипов

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Дженерики (инвариантность, ковариантность и контрвариантность,

A

Формально, ковариантность/контравариантность типов – это сохранение/обращение порядка наследования для производных типов. Проще говоря, когда у ковариантных сущностей типами-параметрами являются родитель и наследник, они сами становятся как бы родителем и наследником. Контравариантные наоборот, становятся наследником и родителем.

Легче всего осознать эти понятия на примерах:
🔘 Ковариантность: List можно присвоить в переменную типа List (как будто он наследник List).
🔘 Контравариантность: в качестве параметра метода List#sort типа Comparator может быть передан Comparator (как будто он родитель Comparator)

Инвариантность – это отсутствие свойств ковариантности и контрвариантности. Дженерики без вайлдкардов инвариантны: List нельзя положить ни в переменную типа List, ни в List.

Массивы ковариантны: в переменную Object[] можно присвоить значение типа String[].

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Множественные ограничения

A

Также можно установить сразу несколько ограничений. Например, пусть класс Transaction может работать только с объектами, которые одновременно реализуют интерфейс Accountable и являются наследниками класса Person:

class Person{}
interface Accountable{}

class Transaction{}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly