Kolekcje Java przechowują tylko obiekty, a nie typy pierwotne; jednak możemy przechowywać klasy opakowania.
Dlaczego to ograniczenie?
java
collections
types
primitive-types
JavaUser
źródło
źródło
class
maszynę JVM. Instrukcjaint i = 1
definiuje wskaźnik do pojedynczej instancji obiektu, który definiujeint
w JVM, ustawioną na wartość1
zdefiniowaną gdzieś w JVM. Tak, wskaźniki w Javie - jest to po prostu oddzielone od użytkownika przez implementację języka. Prymitywy nie mogą być używane jako typy ogólne, ponieważ język przewiduje, że wszystkie typy ogólne muszą być typu nadrzędnegoObject
- stąd dlaczegoA<?>
kompiluje się doA<Object>
w czasie wykonywania.Odpowiedzi:
To była decyzja projektowa w Javie i niektórzy uważają ją za błąd. Kontenery chcą Objects i prymitywy nie pochodzą od Object.
Jest to jedyne miejsce, którego projektanci .NET nauczyli się od JVM i zaimplementowali typy wartości i typy ogólne, tak że w wielu przypadkach wyeliminowano boks. W środowisku CLR kontenery ogólne mogą przechowywać typy wartości jako część podstawowej struktury kontenera.
Java zdecydowała się na dodanie ogólnej obsługi w 100% w kompilatorze bez wsparcia ze strony JVM. JVM jest tym, czym jest, nie obsługuje obiektu „niebędącego obiektem”. Java generics pozwala udawać, że nie ma opakowania, ale nadal płacisz cenę wydajności boksu. Jest to WAŻNE w przypadku niektórych klas programów.
Boks to techniczny kompromis i wydaje mi się, że to szczegóły implementacji przeciekają do języka. Autoboxing jest fajnym cukrem syntaktycznym, ale nadal stanowi spadek wydajności. Jeśli już, chciałbym, aby kompilator ostrzegał mnie, gdy uruchamia się autobox. (Z tego co wiem, może teraz, napisałem tę odpowiedź w 2010 roku).
Dobre wyjaśnienie SO o boksie: Dlaczego niektóre języki wymagają boksu i rozpakowywania?
I krytyka dotycząca typów generycznych Javy: dlaczego niektórzy twierdzą, że implementacja typów ogólnych w Javie jest zła?
W obronie Javy łatwo jest spojrzeć wstecz i krytykować. JVM przetrwał próbę czasu i pod wieloma względami jest dobrym projektem.
źródło
Object.ReferenceEquals
referencji typu,Object
które identyfikują liczby całkowite w pudełku, ale nie powinno być dozwolone przekazać wartość całkowitą]. Automatyczne rozpakowywanie Java jest po prostu nieprzyjemne.Ułatwia wdrażanie. Ponieważ prymitywy Java nie są uważane za obiekty, należy utworzyć oddzielną klasę kolekcji dla każdego z tych prymitywów (brak kodu szablonu do współużytkowania).
Możesz to oczywiście zrobić, po prostu zobacz GNU Trove , Apache Commons Primitives lub HPPC .
O ile nie masz naprawdę dużych kolekcji, narzuty związane z opakowaniami nie mają wystarczającego znaczenia, aby ludzie mogli się nimi zająć (a jeśli masz naprawdę duże prymitywne kolekcje, możesz poświęcić wysiłek na przyjrzenie się użyciu / zbudowaniu dla nich wyspecjalizowanej struktury danych ).
źródło
To połączenie dwóch faktów:
int
nie jestObject
)List<?>
jest naprawdę aList<Object>
w czasie wykonywania)Ponieważ obie te wartości są prawdziwe, ogólne kolekcje Java nie mogą bezpośrednio przechowywać typów pierwotnych. Dla wygody wprowadzono autoboxing, aby umożliwić automatyczne umieszczanie typów pierwotnych w ramkach jako typów referencyjnych. Nie popełnij jednak błędu, kolekcje i tak przechowują odniesienia do obiektów.
Czy można było tego uniknąć? Być może.
int
jestObject
, to w ogóle nie ma potrzeby stosowania typów pudełek.źródło
Istnieje pojęcie auto-boxingu i auto-unboxing. Jeśli spróbujesz zapisać plik
int
w pliku,List<Integer>
kompilator Java automatycznie przekonwertuje go na plikInteger
.źródło
To naprawdę nie jest ograniczenie, prawda?
Zastanów się, czy chcesz utworzyć kolekcję przechowującą wartości pierwotne. Jak napisałeś kolekcję, która może przechowywać int, float lub char? Najprawdopodobniej skończysz z wieloma kolekcjami, więc będziesz potrzebować intlisty, listy charlist itp.
Korzystając z obiektowego charakteru Javy, kiedy piszesz klasę kolekcji, może ona przechowywać dowolny obiekt, więc potrzebujesz tylko jednej klasy kolekcji. Ten pomysł, polimorfizm, jest bardzo potężny i znacznie upraszcza projektowanie bibliotek.
źródło
Myślę, że możemy zobaczyć postęp w tej przestrzeni w JDK prawdopodobnie w Javie 10 opartej na tym JEP - http://openjdk.java.net/jeps/218 .
Jeśli chcesz dziś uniknąć prymitywów boksu w kolekcjach, istnieje kilka alternatyw innych firm. Oprócz wspomnianych wcześniej opcji stron trzecich dostępne są również Eclipse Collections , FastUtil i Koloboke .
Niedawno opublikowano również porównanie pierwotnych map pod tytułem: Large HashMap overview: JDK, FastUtil, Goldman Sachs, HPPC, Koloboke, Trove . Biblioteka GS Collections (Goldman Sachs) została przeniesiona do Eclipse Foundation i obecnie nosi nazwę Eclipse Collections.
źródło
Głównym powodem jest strategia projektowania w Javie. ++ 1) kolekcje wymagają obiektów do manipulacji, a prymitywy nie są wyprowadzane z obiektu, więc może to być inny powód. 2) Prymitywne typy danych Java nie są typami referencyjnymi dla np. int nie jest przedmiotem.
Przezwyciężyć:-
mamy koncepcję auto-boxingu i auto-unboxingu. więc jeśli próbujesz przechowywać prymitywne typy danych, kompilator automatycznie przekonwertuje je na obiekt tej pierwotnej klasy danych.
źródło