JavaRush /Blog Java /Random-PL /Referencyjne typy danych w Javie

Referencyjne typy danych w Javie

Opublikowano w grupie Random-PL
Bez zrozumienia składni Java nie można zostać poważnym programistą, dlatego dzisiaj kontynuujemy naukę składni. W jednym z poprzednich artykułów mówiliśmy o zmiennych prymitywnych, ale ponieważ istnieją dwa typy zmiennych, dzisiaj porozmawiamy o drugim typie - typach referencyjnych w Javie. Więc co to jest? Dlaczego w Javie potrzebne są referencyjne typy danych? Referencyjne typy danych w Javie — 1Wyobraźmy sobie, że mamy obiekt telewizyjny z pewnymi cechami, takimi jak numer kanału, głośność dźwięku i flaga:
public class TV {
   int numberOfChannel;
   int soundVolume;
   boolean isOn;
}
W jaki sposób prosty typ, taki jak , może intprzechowywać te dane? Pamiętajmy: jedna zmienna intto 4 bajty. Ale wewnątrz znajdują się dwie zmienne (4 bajty + 4 bajty) tego samego typu, a także boolean(+1 bajt)... Razem - 4 do 9, ale z reguły w obiekcie przechowywanych jest znacznie więcej informacji. Co robić? Nie można umieścić obiektu w zmiennej. W tym momencie naszej historii pojawiają się zmienne referencyjne. Zmienne referencyjne przechowują adres komórki pamięci, w której znajduje się określony obiekt. Oznacza to, że jest to „wizytówka” z adresem, za pomocą którego możemy znaleźć nasz obiekt w pamięci współdzielonej i wykonać na nim pewne manipulacje. Odwołanie do dowolnego obiektu w Javie jest zmienną referencyjną. Tak by to wyglądało w przypadku naszego obiektu telewizyjnego:
TV telly = new TV();
Ustawiamy zmienną typu TV z nazwą tellyna odnośnik do utworzonego obiektu typu TV. Oznacza to, że JVM przydziela pamięć na stercie dla obiektu TV, tworzy go, a adres jego lokalizacji w pamięci umieszcza w zmiennej telly, która jest przechowywana na stosie. Więcej o pamięci, a mianowicie stosie i wielu innych przydatnych informacjach, możesz przeczytać w tym wykładzie . Zauważyłeś zmienną typu TV i obiekt typu TV? Nie bez powodu: obiekty określonego typu muszą mieć odpowiadające sobie zmienne tego samego typu (nie licząc dziedziczenia i implementacji interfejsu, ale teraz nie bierzemy tego pod uwagę). Przecież nie będziemy nalewać zupy do szklanek, prawda? Okazuje się, że naszym obiektem jest telewizor, a zmienną odniesienia dla niego jest jak panel sterowania. Za pomocą tego pilota możemy wchodzić w interakcję z naszym obiektem i jego danymi. Przykładowo ustaw charakterystykę naszego telewizora:
telly.isOn = true;
telly.numberOfChannel = 53;
telly.soundVolume = 20;
Tutaj użyliśmy operatora kropki ., aby uzyskać dostęp i rozpocząć korzystanie z wewnętrznych elementów obiektu, do którego odnosi się zmienna. Przykładowo w pierwszej linijce powiedzieliśmy zmiennej telly: „Podaj nam zmienną wewnętrzną isOnobiektu, do którego się odwołujesz i ustaw ją na true” (włącz dla nas telewizor).

Redefinicja zmiennych referencyjnych

Załóżmy, że mamy dwie zmienne typu referencyjnego i obiekty, do których się one odnoszą:
TV firstTV = new TV();
TV secondTV = new TV();
Jeśli napiszemy:
firstTV = secondTV;
będzie to oznaczać, że pierwszej zmiennej przypisaliśmy jako wartość kopię adresu (wartość bitów adresu) do drugiego obiektu i teraz obie zmienne odnoszą się do drugiego obiektu (innymi słowy, dwa piloty do tego samego TELEWIZJA). Jednocześnie pierwszy obiekt pozostawiono bez zmiennej, która się do niego odnosi. W efekcie mamy obiekt do którego nie można się dostać, bo zmienna była dla niego takim wątkiem warunkowym, bez którego zamienia się w śmiecie, po prostu leży w pamięci i zajmuje miejsce. Obiekt ten zostanie następnie usunięty z pamięci przez moduł zbierający elementy bezużyteczne . Referencyjne typy danych w Javie — 2Możesz przerwać wątek łączący z obiektem bez innego łącza:
secondTV = null;
W efekcie do obiektu będzie tylko jedno łącze - firstTV, i secondTVnie będzie ono już wskazywało na nikogo (co nie przeszkadza nam w przypisywaniu mu w przyszłości linku do jakiegoś obiektu np. TV).

Klasa string

Osobno chciałbym wspomnieć o klasie String . Jest to klasa bazowa przeznaczona do przechowywania i pracy z danymi przechowywanymi w postaci ciągu znaków. Przykład:
String text = new String("This TV is very loud");
Tutaj przekazaliśmy ciąg znaków, który ma być przechowywany w konstruktorze obiektu. Ale nikt tego nie robi. W końcu można tworzyć ciągi znaków:
String text = "This TV is very loud";
Dużo wygodniej, prawda? Pod względem popularności użycia Stringnie ustępuje typom pierwotnym, jednak nadal jest klasą, a zmienna, która się do niej odwołuje, nie jest typem pierwotnym, a typem referencyjnym. Mamy Stringtę wspaniałą zdolność łączenia ciągów znaków:
String text = "This TV" + " is very loud";
W rezultacie ponownie otrzymamy tekst: This TV is very loud, ponieważ obie linie zostaną połączone w jedną całość, a zmienna będzie odnosić się do tego pełnego tekstu. Ważnym niuansem jest to, że Stringjest to klasa niezmienna. Co to znaczy? Weźmy ten przykład:
String text = "This TV";
text = text + " is very loud";
Wydaje się, że wszystko jest proste: deklarujemy zmienną, nadajemy jej wartość. W następnej linijce to zmieniamy. Ale tak naprawdę się nie zmieniamy. Ponieważ jest to klasa niezmienna, w drugiej linii wartość początkowa nie jest zmieniana, ale tworzona jest nowa, która z kolei składa się z pierwszej + " is very loud".

Stałe odniesienia

W artykule o typach pierwotnych poruszyliśmy temat stałych. Jak zachowa się zmienna referencyjna, gdy zadeklarujemy ją jako ostateczną ?
final TV telly = new TV();
Można by pomyśleć, że dzięki temu obiekt będzie niezmienny. Ale nie, to nieprawda. Referencyjne typy danych w Javie — 3Zmienna referencyjna z modyfikatorem finalzostanie powiązana z konkretnym obiektem bez możliwości odłączenia jej w jakikolwiek sposób (przedefiniowania lub zrównania z null). Oznacza to, że po ustawieniu wartości takiej zmiennej kod taki jak:
telly = new TV();
Lub
telly = null;
spowoduje błąd kompilacji. Oznacza to, że finaldziała tylko na łącze i nie ma wpływu na sam obiekt. Jeśli początkowo mamy go jako zmienny, możemy bez problemu zmienić jego stan wewnętrzny:
telly.soundVolume = 30;
Czasami zmienne są określane jako ostateczne nawet w argumentach metod!
public void enableTV (final TV telly){
   telly.isOn = true;
}
Dzieje się tak, aby podczas pisania metody argumenty te nie mogły zostać przesłonięte i w związku z tym powodowały mniej zamieszania. Co by było, gdybyśmy oznaczyli finalzmienną referencyjną, która odnosi się do niezmiennego obiektu? Np String:
final String PASSWORD = "password";
W rezultacie otrzymamy stałą, analogię stałych typu pierwotnego, ponieważ tutaj nie możemy ani przedefiniować odniesienia, ani zmienić stanu wewnętrznego obiektu (danych wewnętrznych).

Podsumujmy to

  1. Podczas gdy proste zmienne przechowują bity wartości, zmienne referencyjne przechowują bity reprezentujące sposób pobierania obiektu.
  2. Odniesienia do obiektów deklarowane są tylko dla jednego typu obiektu.
  3. Każda klasa w Javie jest typem referencyjnym.
  4. Domyślna wartość dowolnej zmiennej referencyjnej w Javie to null.
  5. Stringjest standardowym przykładem typu referencyjnego. Ta klasa jest również niezmienna.
  6. Zmienne referencyjne z modyfikatorem finalsą przypisane tylko do jednego obiektu bez możliwości redefinicji.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION