
Типи
Java - це статично набрана мова, що означає, що перед використанням потрібно спочатку оголосити змінну та її тип.
Наприклад: int myInteger = 42;
Введіть загальні типи.
Родові типи
Визначення: " Загальний тип - це загальний клас або інтерфейс, який параметризований для типів".
По суті, загальні типи дозволяють писати загальний загальний клас (або метод), який працює з різними типами, що дозволяє повторно використовувати код.
Замість того , щоб вказати obj
, що з int
типу, або String
типу, або будь-якого іншого типу, ви визначаєте Box
клас , щоб прийняти параметр типу <
, T>. Потім ви можете n
використовувати T для представлення цього загального типу в будь-якій частині вашого класу.
Тепер введіть коваріацію та контраваріацію.
Коваріація та контраваріація
Визначення
Варіантність стосується того, як підтипування між більш складними типами відноситься до підтипування між їх компонентами (джерело).
Легко запам’ятовується (і надзвичайно неформальне) визначення коваріації та контраваріації:
- Коваріація: приймаємо підтипи
- Контраваріантність: прийміть супертипи
Масиви
У Java масиви є коваріантними , що має 2 наслідки.
По-перше, масив типу T[]
може містити елементи типу T
та його підтипи.
Number[] nums = new Number[5];nums[0] = new Integer(1); // Oknums[1] = new Double(2.0); // Ok
По-друге, масив типу S[]
є підтипом T[]
if S
є підтипом T
.
Integer[] intArr = new Integer[5];Number[] numArr = intArr; // Ok
Однак важливо пам'ятати, що: (1) numArr
є посиланням на посилальний тип Number[]
на "фактичний об'єкт" intArr
"фактичного типу" Integer[]
.
Отже, наступний рядок буде скомпільований чудово, але створить час виконання ArrayStoreException
(через забруднення купи):
numArr[0] = 1.23; // Not ok
Він створює виняток виконання, оскільки Java знає під час виконання, що "фактичний об'єкт" intArr
насправді є масивом Integer
.
Дженерики
З типовими типами Java не може знати під час виконання інформацію про тип параметрів типу через стирання типу. Таким чином, він не може захистити від забруднення кучі під час роботи.
Таким чином, дженерики є незмінними.
ArrayList intArrList = new ArrayList();ArrayList numArrList = intArrList; // Not okArrayList anotherIntArrList = intArrList; // Ok
Параметри типу повинні точно відповідати, щоб захистити від кучевого забруднення.
Але введіть символи підстановки.
Підстановочні знаки, коваріація та противаріація
За допомогою символів узагальнення генерики можуть підтримувати коваріацію та контраваріацію.
Налаштувавши попередній приклад, ми отримуємо це, що працює!
ArrayList intArrList = new ArrayList();ArrayList numArrList = intArrList; // Ok
Знак питання "?" відноситься до символу підстановки, який представляє невідомий тип. Він може бути нижчим, що обмежує невідомий тип певним типом або його супертипом.
Отже, у рядку 2 ? super Integer
перекладається як "будь-який тип, який є цілим числом або його супертипом".
Ви також можете встановити верхню межу шаблону, який обмежує невідомий тип певним типом або його підтипом, використовуючи ? extends Integer
.
Лише для читання та лише для запису
Коваріація та контраваріація дають цікаві результати. Коваріантні типи доступні лише для читання, тоді як противаріантні типи - лише для читання.
Пам'ятайте, що коваріантні типи приймають підтипи, отже ArrayLister> can contain any object that is either
of a
Number type or its subtype.
In this example, line 9 works, because we can be certain that whatever we get from the ArrayList can be upcasted to a
Number
type (because if it extends Number
, by definition, it is a Number
).
But
nums.add()
doesn’t work, because we cannot be sure of the “actual type” of the object. All we know is that it must be a Number
or its subtypes (e.g. Integer, Double, Long, etc.).
With contravariance, the converse is true.
Line 9 works, because we can be certain that whatever the “actual type” of the object is, it must be
Integer
or its supertype, and thus accept an Integer
object.
But line 10 doesn’t work, because we cannot be sure that we will get an
Integer
. For instance, nums
could be referencing an ArrayList of Objects
.
Applications
Therefore, since covariant types are read-only and contravariant types are write-only (loosely speaking), we can derive the following rule of thumb: “Producer extends, consumer super”.
A producer-like object that produces objects of type
T
can be of type parameter T>, while a consumer-like object that consumes objects of
type T can be of type para
meter super T>.

Original text