TGViewer
Dev Easy Notes Dev Easy Notes @dev_easy_notes · 2.91K subscribers
Post #226 3.49K
Идем дальше, есть три понятия инвариантность, ковариантность и контравариантность. Не пугайтесь названий, сейчас все раскидаем, что поймет каждый. Буду объяснять на примере List и двух классов Developer и MobileDeveloper . Как вы понимаете MobileDeveloper наследует Developer, т.е Developer стоит выше по иерархии наследования. Это значит что мы любую ссылку на MobileDeveloper можем привести к Developer. Типо такого:

MobileDeveloper mobileDeveloper = MobileDeveloper()
Developer developer = mobileDeveloper 


Прежде чем пойдем дальше стоит понять такую штуку, как производный тип. Производный тип получается когда один класс, является одним из компонентов другого типа. Проще на примере, для наших классов это может быть – List<Developer>. List<Developer> – отдельный тип, однако в него входит наш Developer. Думаю тут суть ясна.

Значит, инвариантность это когда List<Developer> и List<MobileDeveloper> это два абсолютно разных типа. Другими словами мы не можем один тип привести к другому. Уже нельзя взять и привести ссылку на список List<MobileDeveloper>, к List<Developer> вас не пропустит компилятор. Все дженерики в Java и в Kotlin по дефолту инвариантные.

Ковариантность это сохранение иерархии в производных типах. Или проще, ковариантность это когда List<MobileDeveloper> является наследником List<Developer>. Раз он наследник, значит можно приводить одну ссылку в другой. Примерно так: 

List<MobileDeveloper> mobileDevelopers = new ArrayList<>();
List<? extends Developer> developers = mobileDevelopers;


Как вы заметили для этого нужно было использовать ? extends Developer. Это и есть синтаксическая реализация ковариантности в Java. Работает это примерно так, когда мы используем строку ? extends Developer мы говорим комплятору, в текущем списке, лежат объекты, которые 100% можно привести к Developer, ведь они или и есть Developer или ниже по иерархии наследованния. 

Для чего это нужно? Очень удобно теперь делать функцию, которая итерируется по списку List<? extends Developer>. Ведь теперь не имеет значение какой именно наследник внутри этого списка. Помимо этого, мы теперь не можем в списке использовать модифицирующие операторы. А вот почему не можем, расскажу в следующем посте.

И последний компонент это Контравариантность. Он противоположен ковариантности. Другими словами контравариантность это когда List<Developer> является наследником List<MobileDeveloper>. Иерархия в производных типах поворачивается на 180 градусов. А пример вот такой:

List<Developer> developers = new ArrayList<>();
List<? super MobileDeveloper> mobileDevelopers = developers;


Синтаксически контравариантность реализуется при помощи ? super MobileDeveloper. Этим мы говорим компилятору, что в списке mobileDevelopers либо MobileDeveloper, либо выше по иерархии. 

Нужно это для того, чтобы делать функции заполнения. Аля такой, вот у меня метод fill(), он принимает вот такой список List<? super MobileDeveloper>. Теперь я могу передавать в этот метод как List<Developer> так и List<MobileDeveloper>, и он отработает одинаково хорошо. Ровно как и с Ковариантностью, у нас минус одна операция. Когда используем ? super MobileDeveloper нельзя использовать операции чтения. Если попробовать использовать get, компилятор упадет. 

Откуда такие ограничения на чтение и запись при контравариантности и ковариантности расскажу в следующем посте. Это одна из самых сложных вещей в дженериках, поймете это, и больше у вас никогда не возникнет проблем.
  • 👍 74
  • 🔥 7
  • 👏 2
  • ❤ 1
More from @dev_easy_notes
  1. Sep 24, 2026На всякий случай напомню напомню, если такую хуйню видите, сразу в бан кидаете. Вы скорее…
  2. Aug 4, 2026Короче, поясню, я давно ничего не пишу, потому что заебался) возможно я скоро вернусь, как…
  3. Aug 4, 2026Post #596
  4. Apr 17, 2026Меня вот что еще дико бесит, через год я буду уже как 10 лет в индустрии и все равно, кажд…
  5. Apr 15, 2026video post
  6. Apr 9, 2026Как оценить работу модели? Часто вижу высказывания в стиле: вот новый клод стал тупее, или…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →