Widzę, że Java ma Boolean (klasa) vs boolean (prymityw). Podobnie istnieje liczba całkowita (klasa) vs int (pierwotna). Jaka jest najlepsza praktyka, kiedy używać prymitywnej wersji w porównaniu z klasą? Czy zasadniczo powinienem zawsze używać wersji klasowej, chyba że mam konkretny (wydajność?) Powód, aby tego nie robić? Jaki jest najczęściej akceptowany sposób korzystania z każdego z nich?
54
Odpowiedzi:
Joshua Bloch mówi w punkcie 5 „Skuteczna Java”
Jednym z dobrych zastosowań klas jest użycie ich jako typów ogólnych (w tym klas Collection, takich jak listy i mapy) lub gdy chcesz je przekształcić w inny typ bez niejawnego rzutowania (na przykład
Integer
klasa ma metodydoubleValue()
lubbyteValue()
.Edycja: Powodem Joshua Blocha jest:
źródło
Standardową praktyką jest stosowanie prymitywów, chyba że masz do czynienia z lekami generycznymi (upewnij się, że wiesz o automatycznym pakowaniu i rozpakowywaniu !).
Istnieje wiele dobrych powodów, aby przestrzegać konwencji:
1. Unikasz prostych błędów:
Istnieją pewne subtelne, nieintuicyjne przypadki, które często łapią początkujących. Nawet doświadczeni koderzy czasami wpadają w błąd i popełniają te błędy (miejmy nadzieję, że po tym debugują kod i wykrywają błąd!).
Najbardziej powszechnym błędem jest użycie
a == b
zamiasta.equals(b)
. Ludzie są przyzwyczajeni do robieniaa == b
prymitywów, więc łatwo to zrobić, gdy używasz opakowań obiektów.2. Czytelność:
Rozważ następujące dwa przykłady. Większość ludzi powiedziałaby, że druga jest bardziej czytelna.
3. Wydajność:
Faktem jest, że jest wolniej używać obwolut obiektu dla prymitywów niż tylko za pomocą prymitywów. Dodajesz koszty tworzenia instancji obiektów, wywołań metod itp. Do rzeczy, których używasz wszędzie .
Cytat Knutha „… mówią w 97% przypadków: przedwczesna optymalizacja jest źródłem wszelkiego zła” tak naprawdę nie ma tutaj zastosowania. Mówił o optymalizacjach, które czynią kod (lub system) bardziej skomplikowanym - jeśli zgadzasz się z punktem # 2, jest to optymalizacja, która sprawia, że kod jest mniej skomplikowany!
4. To konwencja:
Jeśli wybierzesz inne opcje stylistyczne niż 99% innych programistów Java, istnieją 2 wady:
Zwykle wymieniam kilka kontrapunktów, ale szczerze mówiąc, nie mogę wymyślić żadnego dobrego powodu, aby nie iść tutaj na konwencję!
źródło
==
. Obiekty należy porównaćequals()
.equals()
... dajesz im obejście, aby porównanie obiektów z dało==
oczekiwane rezultaty.equals()
do drugiego fragmentu kodu i zmieniłem swój głos.Zwykle idę z prymitywami. Jedną z osobliwości używania klas takich jak
Integer
iBoolean
jest możliwość przypisanianull
do tych zmiennych. Oczywiście oznacza to, że musisznull
cały czas sprawdzać, ale lepiej uzyskać NullPointerException niż mieć błędy logiczne wynikające z użycia niektórych zmiennychint
lubboolean
zmiennych, które nie zostały poprawnie zainicjowane.Oczywiście, ponieważ Java 8 możesz (i prawdopodobnie powinieneś) pójść o krok dalej i zamiast np.
Integer
Możesz użyćOptional<Integer>
dla zmiennych, które mogą mieć lub nie mieć wartości.Dodatkowo wprowadza możliwość użycia
null
do przypisania tym zmiennym wartości „ nieznana ” lub „ symbol wieloznaczny ”. Może to być przydatne w niektórych sytuacjach, na przykład w Ternary Logic . Lub możesz sprawdzić, czy określony obiekt pasuje do jakiegoś szablonu; w takim przypadku możesz użyćnull
tych zmiennych w szablonie, które mogą mieć dowolną wartość w obiekcie.źródło
null
domyślnego przypisania . Przeciwnie: lepiej byłoby w ogóle nie „inicjalizować” zmiennej. Nawet ustawienie dowolnej wartości domyślnejnull
wyłącza kompilator ... ale także zapobiega wykrywaniu braku przydatnego przypisania na wszystkich ścieżkach kodu. Zatem błąd, który mógł wykryć kompilator, przechodzi do środowiska wykonawczego.0.0
, lub-1
, lubInteger.MAX_VALUE
, lubFalse
, ale ostatecznie nie wiesz, czy jest to wartość domyślna, czy rzeczywista wartość przypisana do tej zmiennej. W przypadkach, w których jest to ważne, posiadanienull
wartości może być wyraźniejsze.null
mają wiele problemów, w tym zerową paranoję). W obrębie funkcji zmienna, która może być faktycznie niezainicjowana w punkcie użycia, zazwyczaj wskazuje na nie wykryte przypadki. (Określona analiza przypisań jest uproszczona, więc możliwe są wyniki fałszywie dodatnie. Ale często można je rozwiązać, upraszczając logikę).Słowami laika:
Z opakowań można korzystać, gdy trzeba dodawać elementy do kolekcji.
Kolekcje nie mogą zawierać prymitywów.
źródło
Java wskazuje na autoboxing, jak wskazał m3th0dman. Pomyśl o tym na najniższym możliwym poziomie, a zobaczysz, że prowokacja (wejście lub wyjście) prymitywna wartość będzie oznaczać cykle zegara spędzane na niektórych zadaniach, których nie potrzebujesz, jeśli pracujesz z rodzimymi typami danych wokół aplikacji.
Zasadniczo należy próbować używać rodzimych typów danych, gdy tylko jest to możliwe.
źródło