JavaRush /Blog Java /Random-PL /Zawijanie, rozpakowywanie i pakowanie

Zawijanie, rozpakowywanie i pakowanie

Opublikowano w grupie Random-PL
Cześć! Typy prymitywne są już Ci dość dobrze zaznajomione i dużo z nimi pracowałeś. Zawijanie, rozpakowywanie i pakowanie - 1Prymitywy w programowaniu, a w szczególności w Javie, mają wiele zalet: zajmują mało pamięci, zwiększając w ten sposób wydajność programu i są wyraźnie podzielone na zakresy wartości. Jednak w procesie nauki Javy nieraz powtarzaliśmy jak mantrę: „ w Javie wszystko jest przedmiotem ”. Ale prymitywy są bezpośrednim zaprzeczeniem tych słów. To nie są przedmioty. Zatem zasada „wszystko jest przedmiotem” jest fałszywa? Nie bardzo. W Javie każdy typ pierwotny ma swojego brata bliźniaka, klasę opakowującą ( Wrapper). Co to jest opakowanie? Opakowanie to specjalna klasa, która przechowuje w sobie wartość prymitywu. Ale ponieważ jest to klasa, może tworzyć własne instancje. Będą przechowywać w środku niezbędne prymitywne wartości, będąc jednocześnie prawdziwymi obiektami. Nazwy klas opakowań są bardzo podobne do nazw odpowiednich prymitywów lub całkowicie się z nimi pokrywają. Dlatego bardzo łatwo będzie je zapamiętać.
Klasy opakowań dla pierwotnych typów danych
Pierwotne typy danych Klasy wrapperów
wew Liczba całkowita
krótki Krótki
długi Długi
bajt Bajt
platforma Platforma
podwójnie Podwójnie
zwęglać Postać
wartość logiczna Wartość logiczna
Obiekty klasy wrappera tworzone są tak samo jak inne:
public static void main(String[] args) {

   Integer i = new Integer(682);

   Double d = new Double(2.33);

   Boolean b = new Boolean(false);
}
Klasy otokowe pozwalają złagodzić wady typów pierwotnych. Najbardziej oczywistym jest to, że prymitywy nie mają metod . Na przykład nie mają metody toString(), więc nie można na przykład przekonwertować liczby intna ciąg znaków. Ale dzięki klasie opakowania Integerjest to łatwe.
public static void main(String[] args) {

   Integer i = new Integer(432);

   String s = i.toString();
}
Trudności będą także z transformacją odwrotną. Załóżmy, że mamy ciąg znaków, o którym wiemy na pewno, że zawiera liczbę. Jednak w przypadku typu pierwotnego intnie uda nam się pobrać tej liczby z ciągu znaków i zamienić ją de facto na liczbę. Ale dzięki klasom opakowań mamy teraz taką możliwość.
public static void main(String[] args) {

   String s = "1166628";

   Integer i = Integer.parseInt(s);

   System.out.println(i);
}
Wynik: 1166628 Pomyślnie pobraliśmy liczbę z łańcucha i przypisaliśmy ją do zmiennej referencyjnej Integer i. Przy okazji, o linkach. Wiesz już, że parametry są przekazywane do metod na różne sposoby: elementy pierwotne są przekazywane przez wartość, a obiekty przez referencję. Możesz wykorzystać tę wiedzę podczas tworzenia swoich metod: jeśli Twoja metoda działa na przykład z liczbami ułamkowymi, ale potrzebujesz logiki przekazywania przez referencję, możesz przekazać parametry do metody Double/Floatzamiast double/float. Oprócz metod klasy wrapperowe posiadają pola statyczne, które są bardzo wygodne w użyciu. Na przykład wyobraź sobie, że stoisz przed zadaniem: wypisz na konsoli maksymalną możliwą liczbę int, a następnie minimalną możliwą liczbę. Zadanie wydaje się elementarne, ale bez Google raczej nie uda Ci się go wykonać. A klasy wrapperów z łatwością pozwalają rozwiązać następujące „codzienne problemy”:
public class Main {
   public static void main(String[] args) {

       System.out.println(Integer.MAX_VALUE);
       System.out.println(Integer.MIN_VALUE);
   }
}
Takie pola pozwalają nie odwracać uwagi od poważniejszych zadań. Nie mówiąc już o tym, że w procesie drukowania liczby 2147483647 (jest to dokładnie MAX_VALUE) nie dziwi jej błędne wpisanie :) Dodatkowo w jednym z poprzednich wykładów zwracaliśmy już uwagę na fakt, że obiekty klas wrapperów są niezmienne (Immutable) .
public static void main(String[] args) {

   Integer a = new Integer(0);
   Integer b = new Integer(0);

   b = a;
   a = 1;
   System.out.println(b);
}
Wynik: 0 Obiekt, na który pierwotnie wskazywało odniesienie, аnie zmienił swojego stanu, w przeciwnym razie wartość brównież by się zmieniła. Podobnie jak w przypadku Stringzamiast zmieniać stan obiektu opakowania, w pamięci tworzony jest zupełnie nowy obiekt. Dlaczego twórcy Javy ostatecznie zdecydowali się zachować w języku typy pierwotne? Ponieważ wszystko powinno być obiektem, a mamy już klasy opakowań, których można użyć do wyrażenia wszystkiego, co wyrażają prymitywy, dlaczego po prostu nie zostawić ich w języku i usunąć prymitywy? Odpowiedź jest prosta – wydajność. Typy prymitywne nazywane są prymitywnymi, ponieważ pozbawione są wielu „ciężkich” cech obiektów. Tak, obiekt ma wiele wygodnych metod, ale nie zawsze ich potrzebujesz. Czasami wystarczy liczba 33, 2,62 lub wartość true/ false. W sytuacjach, gdy wszystkie zalety obiektów nie są ważne i nie są potrzebne do działania programu, prymitywy spisują się znacznie lepiej.

Automatyczne pakowanie/automatyczne rozpakowywanie

Jedną z cech prymitywów i ich klas opakowań w Javie jest autoboxing/autounboxing.Przyjrzyjmy Zawijanie, rozpakowywanie i pakowanie - 2 się tej koncepcji. Jak już dowiedzieliśmy się wcześniej, Java jest językiem obiektowym. Oznacza to, że wszystkie programy napisane w Javie składają się z obiektów. Prymitywy nie są obiektami. Jednakże zmiennej klasy opakowania można przypisać wartość typu pierwotnego. Proces ten nazywa się autoboxingiem . W ten sam sposób zmiennej typu pierwotnego można przypisać obiekt klasy opakowania. Proces ten nazywa się automatycznym unboxingiem . Na przykład:
public class Main {
   public static void main(String[] args) {
       int x = 7;
       Integer y = 111;
       x = y; // automatyczne rozpakowywanie
       y = x * 123; // automatyczne pakowanie
   }
}
W linii 5 przypisujemy prymitywowi x wartość y, która jest obiektem klasy opakowującej Integer. Jak widać, nie są do tego potrzebne żadne dodatkowe działania: kompilator o tym wie inti Integerwłaściwie to samo . To jest automatyczne rozpakowywanie. To samo dzieje się z autoboxingiem w linii 6: obiektowi y można łatwo przypisać wartość prymitywów (x*123). To jest przykład automatycznego pakowania. Dlatego dodano słowo „auto”: aby przypisać pierwotne odniesienia do obiektów ich klas opakowań (i odwrotnie), nie trzeba nic robić, wszystko dzieje się automatycznie . Wygodne, prawda? :) Kolejna bardzo duża wygoda automatycznego pakowania/automatycznego rozpakowywania przejawia się w działaniu metod. Faktem jest, że parametry metody również podlegają autopakowaniu i autorozpakowaniu . I na przykład, jeśli jeden z nich przyjmuje na wejściu dwa obiekty Integer, możemy łatwo przekazać tam zwykłe prymitywy int!
public class Main {
   public static void main(String[] args) {

       printNumber(7);//zwykły int, nawet bez zmiennej
   }

   public static void printNumber(Integer i) {
       System.out.println(„Wpisałeś numer” + i);
   }
}
Wynik: Wpisałeś liczbę 7. Działa to w drugą stronę:
public class Main {
   public static void main(String[] args) {

       printNumber(new Integer(632));
   }

   public static void printNumber(int i) {
       System.out.println(„Wpisałeś numer” + i);
   }
}
Ważna uwaga do zapamiętania: automatyczne pakowanie i rozpakowywanie nie działa w przypadku tablic !
public class Main {
   public static void main(String[] args) {

       int[] i = {1,2,3,4,5};

       printArray(i);//błąd, nie kompiluje się!
   }

   public static void printArray(Integer[] arr) {
       System.out.println(Arrays.toString(arr));
   }
}
Próba przekazania tablicy elementów podstawowych do metody pobierającej tablicę obiektów jako dane wejściowe spowoduje błąd kompilacji. Na koniec jeszcze raz krótko porównajmy prymitywy i opakowania Prymitywy:
  • mają przewagę wydajnościową
Owijarki:
  • Pozwalają nie naruszać zasady „wszystko jest przedmiotem”, dzięki czemu liczby, symbole i wartości logiczne prawda/fałsz nie wypadają z tego pojęcia
  • Rozszerz możliwość pracy z tymi wartościami, udostępniając wygodne metody i pola
  • Konieczne, gdy jakaś metoda może działać wyłącznie z obiektami
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION