Для повного розуміння головної причини цього потрібен певний контекст.
Примітиви проти класів
Примітивні змінні в Java містять значення (ціле число, двійкове число з плаваючою комою з подвійною точністю тощо). Оскільки ці значення можуть мати різну довжину , змінні, що їх містять, також можуть мати різну довжину (враховуйте floatпроти double).
З іншого боку, змінні класу містять посилання на екземпляри. Посилання зазвичай реалізуються як покажчики (або щось дуже схоже на покажчики) на багатьох мовах. Ці речі , як правило , мають однаковий розмір, незалежно від розмірів випадків вони відносяться ( Object, String, Integerі т.д.).
Ця властивість змінних класу робить посилання, які вони містять, взаємозамінними (до певної міри). Це дозволяє нам робити те, що ми називаємо заміною : загалом кажучи, використовувати екземпляр певного типу як екземпляр іншого, пов'язаного типу (використовувати a Stringяк an Object, наприклад).
Примітивні змінні не є взаємозамінними однаково, ні між собою, ні з Object. Найбільш очевидною причиною цього (але не єдиною причиною) є їх різниця в розмірах. Це робить примітивні типи незручними в цьому відношенні, але вони все ще потрібні в мові (з причин, які в основному зводяться до продуктивності).
Загальні засоби та стирання типу
Загальні типи - це типи з одним або кількома параметрами типу (точна кількість називається загальною сутністю ). Наприклад, загальне визначення типу List<T> має параметр типу T, який може бути Object(створення конкретного типу List<Object> ), String( List<String>), Integer( List<Integer>) тощо.
Загальні типи набагато складніші, ніж не-загальні типи. Коли вони були введені в Java (після її первісного випуску), щоб уникнути кардинальних змін у JVM і, можливо, порушити сумісність зі старими двійковими файлами, творці Java вирішили впровадити загальні типи найменш інвазивним способом: усі конкретні типи List<T>насправді компілюються в (двійковий еквівалент) List<Object>(для інших типів прив’язка може бути чимось іншим Object, але ви розумієте). Інформація про загальну сутність та параметри типу втрачається в цьому процесі , саме тому ми називаємо це стиранням типу .
Поклавши два разом
Тепер проблема полягає в поєднанні вищезазначених реалій: якщо це List<T>стає List<Object>у всіх випадках, то Tзавжди повинен бути тип, якому можна безпосередньо призначитиObject . Нічого іншого не можна допускати. Оскільки, як ми вже говорили раніше, int, floatі doubleне є взаємозамінними Object, може не бути List<int>, List<float>або List<double>(якщо значно складніша реалізація дженериків не існувало в JVM).
Але Java типи таких пропозицій Integer, Floatі Doubleякі обернути ці примітиви в екземпляри класу, що робить їх ефективно взаємозамінні , як Object, таким чином , дозволяючи загальні типи , побічно роботи з примітивами , а також (тому що ви можете мати List<Integer>, List<Float>, List<Double>і так далі).
Процес створення ан Integerз а int, а Floatз floatа тощо називається боксом . Реверс називається розпаковуванням . Оскільки доводиться кодувати примітиви кожного разу, коли ви хочете їх використовувати, як Objectце незручно, бувають випадки, коли мова робить це автоматично - це називається автобокс .