Kiedy powinienem wybrać klasę opakowującą zamiast typów pierwotnych? Lub w jakich okolicznościach powinienem wybierać między typami opakowującymi / pierwotnymi?
Odpowiedzi:
Inni wspominali, że niektóre konstrukcje, takie jak Collections
wymagają obiektów, i że obiekty mają więcej narzutów niż ich prymitywne odpowiedniki (pamięć i boks).
Inną kwestią jest:
Przydatne może być zainicjowanie obiektów null
lub wysłanie null
parametrów do metody / konstruktora w celu wskazania stanu lub funkcji. Nie można tego zrobić z prymitywami.
Wielu programistów inicjuje liczby na 0 (domyślnie) lub -1, aby to oznaczyć, ale w zależności od scenariusza może to być niepoprawne lub wprowadzające w błąd.
Spowoduje to również ustawienie sceny, NullPointerException
gdy coś jest używane nieprawidłowo, co jest znacznie bardziej przyjazne dla programisty niż jakiś arbitralny błąd w przyszłości .
Ogólnie rzecz biorąc, powinieneś używać typów pierwotnych, chyba że z jakiegoś powodu potrzebujesz obiektu (np. Aby umieścić w kolekcji). Nawet wtedy rozważ inne podejście, które nie wymaga obiektu, jeśli chcesz zmaksymalizować wydajność numeryczną. Zaleca się to w dokumentacji , a ten artykuł pokazuje, jak automatyczne boksowanie może powodować duże różnice w wydajności.
Integer
jest bardziej czytelny niż int
.
Moim zdaniem, jeśli składowe mojej klasy są zmiennymi opakowującymi, nie opiera się na wartościach domyślnych, co jest zachowaniem przyjaznym dla programistów.
1.
class Person {
int SSN ; // gets initialized to zero by default
}
2.
class PersonBetter {
Integer SSN; //gets initialized to null by default
}
W pierwszym przypadku nie można pozostawić niezainicjowanej wartości numeru PESEL. Może to zaszkodzić, jeśli nie sprawdzisz, czy wartość została ustawiona przed próbą jej użycia.
W drugim przypadku możesz zachować inicjalizację numeru SSN z wartością null. Co może prowadzić do wyjątku NullPointerException, ale jest lepsze niż nieświadome wstawianie wartości domyślnych (zero) jako numeru SSN do bazy danych za każdym razem, gdy próbujesz go użyć bez inicjowania pola SSN.
PersonBuilder
który zgłasza wyjątek, jeśli numer SSN nie jest ustawiony przed wywołaniem „kompilacji” w celu pobrania Person
instancji. Myślę, że tego rodzaju rzeczy są przesadne, ale to właśnie język Java promuje dla odpowiednich wzorców.
Użyłbym tylko typów opakowań, jeśli musisz.
Korzystając z nich niewiele zyskujesz, poza tym, że są Objects
.
I tracisz narzuty związane z użyciem pamięci i czasem spędzonym na boksowaniu / rozpakowywaniu.
Praktycznie spotkałem się z sytuacją, w której można wyjaśnić użycie klasy opakowującej.
Utworzyłem klasę usług, która miała long
zmienną typu
long
- gdy nie zostanie zainicjowana, zostanie ustawiona na 0 - będzie to mylące dla użytkownika, gdy zostanie wyświetlona w GUI Long
- gdy nie zostanie zainicjowana, zostanie ustawiona na null
- ta wartość null nie pojawi się w GUI.Dotyczy to Boolean
również przypadków, w których wartości mogą być bardziej zagmatwane, gdy używamy prymitywów boolean
(ponieważ wartość domyślna to fałsz).
Kolekcje są typowym przypadkiem dla prostych obiektów opakowania Java. Można jednak rozważyć nadanie Wrapperowi bardziej szczegółowego znaczenia w kodzie (obiekt wartości).
IMHO prawie zawsze istnieje korzyść z używania obiektów wartości, gdy sprowadza się to do czytelności i utrzymania kodu. Pakowanie prostych struktur danych wewnątrz obiektów, gdy mają one określone obowiązki, często upraszcza kod. Jest to bardzo ważne w projektowaniu opartym na domenie .
Istnieje oczywiście problem z wydajnością, ale zwykle go ignoruję, dopóki nie będę miał możliwości zmierzenia wydajności za pomocą odpowiednich danych i podjęcia bardziej ukierunkowanych działań na problematyczny obszar. Zrozumienie problemu z wydajnością może być również łatwiejsze, jeśli kod jest również łatwy do zrozumienia.
Wydajność aplikacji zdominowanych przez obliczenia numeryczne może znacznie skorzystać na zastosowaniu prymitywów.
typy prymitywne, używa się operatora ==, ale w przypadku opakowania preferowanym wyborem jest wywołanie metody equals ().
„Typy prymitywne uważane za szkodliwe” ponieważ łączą ”semantykę proceduralną w jednolity model zorientowany obiektowo.
Wielu programistów inicjuje liczby na 0 (domyślnie) lub -1, aby to oznaczyć, ale w zależności od scenariusza może to być niepoprawne lub wprowadzające w błąd.
Jeśli chcesz korzystać z kolekcji, musisz użyć klas Wrapper.
Typy prymitywne są używane w tablicach. Ponadto, aby przedstawić dane, które nie mają żadnego zachowania, na przykład licznik lub warunek logiczny.
Od czasu autoboxingu granica „kiedy używać prymitywu lub opakowania” stała się dość niewyraźna.
Pamiętaj jednak, że opakowania to obiekty, więc masz wszystkie wymyślne funkcje Java. Na przykład, możesz użyć reflexion do tworzenia obiektów Integer, ale nie wartości int. Klasy opakowujące mają również metody, takie jak valueOf.
Jeśli chcesz utworzyć typ wartości. Coś w rodzaju ProductSKU lub AirportCode.
Kiedy typ pierwotny (łańcuch w moich przykładach) definiuje równość, będziesz chciał zastąpić równość.
Wartości pierwotne w Javie nie są obiektami. Aby móc manipulować tymi wartościami jako obiektami, pakiet java.lang udostępnia klasę opakowania dla każdego pierwotnego typu danych.
Wszystkie klasy Wrapper są ostateczne. Obiekty wszystkich klas opakowania, które można zainicjować, są niezmienne, co oznacza, że nie można zmienić wartości obiektu opakowania.
Chociaż klasa void jest uważana za klasę opakowania, ale nie zawija żadnych wartości pierwotnych i nie można jej zainicjować. Nie ma konstruktora publicznego, po prostu oznacza obiekt klasy reprezentujący słowo kluczowe void.