Aby w pełni zrozumieć główny powód takiego stanu rzeczy, potrzebny jest kontekst.
Prymitywy a klasy
Zmienne pierwotne w Javie zawierają wartości (liczbę całkowitą, liczbę binarną zmiennoprzecinkową podwójnej precyzji itp.). Ponieważ te wartości mogą mieć różne długości , zawierające je zmienne mogą również mieć różne długości (rozważ w floatporównaniu double).
Z drugiej strony zmienne klasowe zawierają odniesienia do instancji. Odnośniki są zwykle implementowane jako wskaźniki (lub coś bardzo podobnego do wskaźników) w wielu językach. Te rzeczy mają zwykle ten sam rozmiar, niezależnie od wielkości tych przypadkach, których dotyczą ( Object, String, Integer, etc).
Ta właściwość zmiennych klasowych sprawia, że zawarte w nich odwołania są wymienne (do pewnego stopnia). To pozwala nam robić to, co nazywamy substytucją : mówiąc ogólnie, używać instancji określonego typu jako instancji innego, pokrewnego typu ( na przykład użyj a Stringjako Object).
Zmienne pierwotne nie są zamienne w ten sam sposób, ani między sobą, ani z Object. Najbardziej oczywistym powodem tego (ale nie jedynym) jest różnica w wielkości. To sprawia, że typy prymitywne są pod tym względem niewygodne, ale nadal potrzebujemy ich w języku (z powodów, które sprowadzają się głównie do wydajności).
Typy ogólne i usuwanie typów
Typy ogólne to typy z co najmniej jednym parametrem typu (dokładna liczba nazywana jest liczbą ogólną ). Na przykład definicja typu ogólnego List<T> ma parametr typu T, którym może być Object(tworzenie konkretnego typu List<Object> ), String( List<String>), Integer(List<Integer> ) i tak dalej.
Typy ogólne są o wiele bardziej skomplikowane niż nieogólne. Kiedy zostały wprowadzone do Javy (po jej pierwszym wydaniu), aby uniknąć radykalnych zmian w JVM i być może zerwania kompatybilności ze starszymi plikami binarnymi, twórcy Javy zdecydowali się zaimplementować typy generyczne w jak najmniej inwazyjny sposób: wszystkie konkretne typy List<T>są w rzeczywistości skompilowane do (binarnego odpowiednika) List<Object>(dla innych typów powiązanie może być czymś innym niż Object, ale o co chodzi). W procesie tym następuje utrata ogólnych informacji o wartościach i parametrach typu , dlatego nazywamy to wymazywaniem typu .
Łącząc te dwie rzeczy razem
Teraz problem jest kombinacja powyższych realia: jeśli List<T>staje się List<Object>we wszystkich przypadkach, po czym Tzawsze musi być typu, które mogą być bezpośrednio przypisaneObject . Nie można pozwolić na nic innego. Ponieważ, jak już powiedzieliśmy, int, floati doublenie są wymienne z Object, tam nie może być List<int>, List<float>lubList<double> (chyba znacznie bardziej skomplikowane wdrożenie generycznych istniał w JVM).
Ale Java oferty rodzaje podoba Integer, Floata Doublektóry zawijać tych prymitywów w instancji klasy, dzięki czemu skutecznie jako substytucyjne Object, a tym samym pozwalając typy generyczne pośrednio pracy z prymitywów , jak również (bo może mieć List<Integer>, List<Float>,List<Double> i tak dalej).
Proces tworzenia Integerze związku int, A Floatod A floati tak dalej, nazywany jest boks . Odwrotność nazywa się unboxing . Ponieważ konieczność zaznaczania prymitywów za każdym razem, gdy chcesz ich używać, Objectjest niewygodna, są przypadki, w których język robi to automatycznie - nazywa się to autoboxingiem .