Generics

Открыта

— Привет, Амиго!

— Привет, Элли!

— Сегодня мы с Ришей собираемся рассказать тебе все о generic’ах.

— Так я уже вроде бы почти все знаю.

— Почти все, да не все.

— Да? Ладно, я готов слушать.

— Тогда начнем.

Generic’ами в Java, называют классы, которые содержат типы-параметры.

Причины появления generic’ов – см. комментарий в коде:

Пример
ArrayList stringList = new ArrayList();
stringList.add("abc"); //добавляем строку в список
stringList.add("abc"); //добавляем строку в список
stringList.add( 1 ); //добавляем число в список

for(Object o: stringList)
{
 String s = (String) o; //тут будет исключение, когда дойдем до элемента-числа
}

Как решают проблему Generic’и:

Пример
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("abc"); //добавляем строку в список
stringList.add("abc"); //добавляем строку в список
stringList.add( 1 ); //тут будет ошибка компиляции

for(Object o: stringList)
{
 String s = (String) o;
}

Такой код просто не скомпилируется, и ошибка с добавлением данных не того типа будет замечена еще на этапе компиляции.

— Я это уже знаю.

— Вот и отлично. Повторение — мать учения.

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

Код с generic’ами
List<String> strings = new ArrayList<String>();
strings.add("abc");
strings.add("abc");
strings.add( 1); // тут ошибка компиляции

for(String s: strings)
{
 System.out.println(s);
}
Что происходит на самом деле
List strings = new ArrayList();

strings.add((String)"abc");
strings.add((String)"abc");
strings.add((String) 1); //ошибка компиляции

for(String s: strings)
{
 System.out.println(s);
}

— Хитро, да.

— Да, но у этого подхода есть побочный эффект. Внутри класса-generic’а не хранится никакой информации о его типе-параметре. Такой подход позже назвали стиранием типов.

Т.е. если у тебя есть свой класс с типами-параметрами, то ты не можешь использовать информацию о них внутри класса.

Код с generic’ами
class Zoo<T>
{
 ArrayList<T> pets = new ArrayList<T>();

 public T createAnimal()
 {
  T animal = new T();
  pets.add(animal)
  return animal;
 }
}
Что происходит на самом деле
class Zoo
{
 ArrayList pets = new ArrayList();

 public Object createAnimal()
 {
  Object animal = new ???();
 pets.add(animal)
  return animal;
 }
}

При компиляции все типы параметров заменяются на Object. И информации о типе, который в него передавали, в классе нет.

— Да, согласен, это не очень хорошо.

— Ладно, все не так страшно, я тебе позже расскажу, как эту проблему научились обходить.

Но и это еще не все. Java позволяет задать тип-родитель для типов-параметров. Для этого используется ключевое слово extends. Пример:

Код с generic’ами
class Zoo<T extends Cat>
{
 T cat;

 T getCat()
 {
  return cat;
 }

 void setCat (T cat)
 {
  this.cat = cat;
 }

 String getCatName() { return this.cat.getName(); }
}
Что происходит на самом деле
class Zoo
{
 Cat cat;

 Cat getCat()
 {
  return cat;
 }

 void setCat(Cat cat)
 {
  this.cat = cat;
 }

 String getCatName() { return this.cat.getName(); }
}

Обрати внимание на два факта.

Во-первых, в качестве типа параметра теперь можно передать не любой тип, а тип Cat или один из его наследников.

Во-вторых, в классе Zoo у переменных типа T теперь можно вызвать методы класса Cat. Почему – объяснено в столбце справа (потому что вместо типа T везде подставится тип Cat)

— Ага. Если мы сказали, что в качестве типа-параметра у нас передают тип Cat или его наследников, значит, мы уверены, что методы класса Cat у типа T обязательно есть.

Что ж. Умно.

Комментарии (38)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
КожаныйЧервь
Уровень 49
9 февраля, 14:45
https://www.youtube.com/watch?v=iQIR2Zgb93k вот видос где все понятно рассказывают.
Denis Odesskiy Full Stack Developer
14 ноября 2024, 12:53
"Но разработчики Java немного схалявили при создании Generic"... Это было сделано не потому что "они схалявили", а для обратной совместимости с кодом в котором этих самых дженериков не было. Например в C# если мне память не изменяет, типы не стираются.... Статья Стирание типов
Алексей С
Уровень 33
7 июля 2023, 23:55
А когда будут соники))
Deniel Java Developer
10 января 2023, 13:05
Дженерики и вправду полезная штука
wokku
Уровень 51
17 июля 2023, 16:03
😂
Виктор
Уровень 1
8 декабря 2022, 19:14
Простое и понятное объяснение: Дженерики в Java для самых маленьких: синтаксис, границы и дикие карты Еще хорошее объяснение есть на метаните (ищите ссылку ниже) Ну и что бы было у всех на виду, буквы дженериков: E — element, для элементов параметризованных коллекций; K — key, для ключей map-структур; V — value, для значений map-структур; N — number, для чисел; T — type, для обозначения типа параметра в произвольных классах; S, U, V и так далее — применяются, когда в дженерик-классе несколько параметров. The Java™ Tutorials - Generic Types
Maks PanteleevJava Developer в Bell Integrator
15 июля 2021, 14:37
Дженерики это как рекурсия и this - ты либо чувствуешь сердцем, либо таращишь глаза и плачешь
Hidden #213 Урoвень 13 (Forever&Ever)
27 марта 2022, 07:22
😭😭😭 как боженька смолвил
Oleg Khilko
Уровень 51
9 августа 2022, 14:47
Макс, ты шикарен!💪👍 Отлично сказано!
FatCat Backend Developer
28 сентября 2022, 14:30
Восхитительно сказал, я даже сквозь слезы твой коммент смог прочитать)
Limone Scala Dev
28 января 2021, 17:41
Просто пропиарю здесь огромный FAQ по дженерикам из рекомендаций Хорстманна, куда можно заглядывать каждый раз, когда забыл, как быстро и с гарантией устроить heap pollution, или задаёшься смутными вопросами "Можно ли заоверрайдить дженерик метод другим дженерик методом?" "Почему нет enum-дженериков?" и "Кто такая эта ваша реификация".)
NikeMirum
Уровень 41
20 октября 2020, 07:32
Вроде бы простая тема, но у меня почему-то вызвала больше всего недоумения из всех пройденных. Особенно сложно въезжать было в: "Но разработчики Java немного схалявили при создании Generic и вместо того, чтобы делать полноценные типы с параметрами прикрутили хитрую оптимизацию. На самом деле в типы не добавили никакой информации о их типах-параметрах, а вся магия происходила на этапе компиляции."
Максим
Уровень 36
5 марта 2020, 06:48
Очередная лекция на наркоманском языке. И как всегда комментарии рулят )))
Vorlock
Уровень 31
23 января 2020, 17:43
в сэмпле "Код с generic’ами" и "Что происходит на самом деле" ошибка в 8й строке - пропущен ";" и что это за ересь "Object animal = new ???();" зы: за такой стайл написания на проектах ногами бьют
JustinianJudge в Mega City OneMaster
2 мая 2020, 00:53
злые у вас там на проекте, постарайся больше так не подставляться