Cześć! Przeglądając JavaRush, natrafiłeś na typy pierwotne więcej niż raz. Oto krótka lista tego, co o nich wiemy:
Ale oprócz wartości typy różnią się także rozmiarem pamięci.
Typ
- Nie są one obiektami i reprezentują wartość przechowywaną w pamięci
- Istnieje kilka typów typów pierwotnych:
- Wszystkie liczby -
byte
,short
,int
,long
- Liczby zmiennoprzecinkowe (ułamkowe) -
float
idouble
- Wartość logiczna -
boolean
- Symboliczne (do wskazania liter i cyfr) -
char
- Wszystkie liczby -
- Każdy z nich ma swój własny zakres wartości:
Typ prymitywny | Rozmiar w pamięci | Zakres wartości |
---|---|---|
bajt | 8 bitowy | -128 do 127 |
krótki | 16-bitowy | do -32768 do 32767 |
zwęglać | 16-bitowy | od 0 do 65536 |
wew | 32 bity | od -2147483648 do 2147483647 |
długi | 64 bity | od -9223372036854775808 do 9223372036854775807 |
platforma | 32 bity | od (2 do potęgi -149) do ((2-2 do potęgi -23)*2 do potęgi 127) |
podwójnie | 64 bity | od (-2 do potęgi 63) do ((2 do potęgi 63) - 1) |
wartość logiczna | 8 (w przypadku użycia w tablicach), 32 (w przypadku użycia w przypadku innych niż tablice) | prawda czy fałsz |
int
zajmuje więcej niż byte
. A long
– więcej niż short
. Ilość pamięci zajmowanej przez prymitywy można porównać do lalek gniazdujących: Wewnątrz lalki gniazdującej jest wolne miejsce. Im większa lalka do gniazdowania, tym więcej miejsca. long
Mniejszą z łatwością zmieścimy w dużej lalce lęgowej int
. Pasuje łatwo i nie musisz robić nic więcej. W Javie podczas pracy z elementami podstawowymi nazywa się to konwersją automatyczną. W inny sposób nazywa się to rozszerzeniem. Oto prosty przykład rozszerzenia:
public class Main {
public static void main(String[] args) {
int bigNumber = 10000000;
byte littleNumber = 16;
bigNumber = littleNumber;
System.out.println(bigNumber);
}
}
Tutaj przypisujemy wartość byte
zmiennej int
. Przypisanie przebiegło pomyślnie i bez żadnych problemów: wartość przechowywana w byte
zajmuje mniej miejsca w pamięci, niż „mieści się” w int
. „Mała laleczka gniazdująca” (wartość byte
) z łatwością mieści się w „dużej matrioszce” (zmienna int
). Co innego, jeśli spróbujesz zrobić odwrotnie – wstaw dużą wartość do zmiennej, która nie jest zaprojektowana dla takich rozmiarów. Zasadniczo ta sztuczka nie zadziała z prawdziwymi lalkami gniazdującymi, ale w Javie będzie działać, ale z niuansami. Spróbujmy umieścić wartość int
w zmiennej short
:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = bigNumber;//błąd!
System.out.println(bigNumber);
}
Błąd! Kompilator rozumie, że próbujesz zrobić coś niestandardowego i umieszcza dużą lalkę matrioszki ( int
) w małej ( short
). Błąd kompilacji w tym przypadku jest ostrzeżeniem kompilatora: „ Hej, czy na pewno chcesz to zrobić? „Jeśli jesteś pewien, powiedz o tym kompilatorowi: „ Wszystko jest w porządku, wiem, co robię!” Ten proces nazywa się jawną konwersją typu lub zawężaniem . Aby dokonać zawężenia, musisz wyraźnie wskazać typ, na który chcesz rzutować swoją wartość. Innymi słowy, odpowiedz na pytanie kompilatora: „ No cóż, w której z tych małych lalek chcesz umieścić tę dużą lalkę?” W naszym przypadku będzie to wyglądać następująco:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = (short) bigNumber;
System.out.println(littleNumber);
}
Wyraźnie wskazaliśmy, że chcemy dopasować wartość int
do zmiennej short
i wziąć za to odpowiedzialność. Kompilator, widząc wyraźne wskazanie węższego typu, wykonuje konwersję. Jaki będzie wynik? Dane wyjściowe konsoli: -27008 Trochę nieoczekiwane. Dlaczego właśnie tak? To właściwie proste. Pierwotnie mieliśmy wartość - 10000000. Została ona zapisana w zmiennej int
, która zajmowała 32 bity, a w formie binarnej wyglądała tak: Zapisujemy tę wartość do zmiennej short
, ale może ona przechowywać tylko 16 bitów! W związku z tym zostanie tam przeniesionych tylko pierwszych 16 bitów naszego numeru, reszta zostanie odrzucona. W rezultacie zmienna short
będzie zawierać wartość , która w postaci dziesiętnej jest dokładnie równa -27008. Dlatego kompilator „poprosił o potwierdzenie” w postaci jawnego rzutowania na konkretny typ. Po pierwsze, pokazuje, że bierzesz odpowiedzialność za wynik, a po drugie, mówi kompilatorowi, ile miejsca przydzielić podczas rzutowania typów. Przecież gdybyśmy w ostatnim przykładzie rzutowali int
na type byte
, a nie na short
, mielibyśmy do dyspozycji tylko 8 bitów, a nie 16, i wynik byłby inny. W przypadku typów ułamkowych ( float
i double
) zwężanie przebiega inaczej. Jeśli spróbujesz zamienić taką liczbę na liczbę całkowitą, jej część ułamkowa zostanie odrzucona.
public static void main(String[] args) {
double d = 2.7;
long x = (int) d;
System.out.println(x);
}
Wyjście konsoli: 2
Typ danych char
Wiesz już, że typ char służy do wyświetlania pojedynczych znaków.public static void main(String[] args) {
char c = '!';
char z = 'z';
char i = '8';
}
Ale ma wiele funkcji, które należy zrozumieć. Spójrzmy jeszcze raz na tabelę z zakresami wartości:
Typ prymitywny | Rozmiar w pamięci | Zakres wartości |
---|---|---|
bajt | 8 bitowy | -128 do 127 |
krótki | 16-bitowy | -32768 do 32767 |
zwęglać | 16-bitowy | od 0 do 65536 |
wew | 32 bity | od -2147483648 do 2147483647 |
długi | 64 bity | od -9223372036854775808 do 9223372036854775807 |
platforma | 32 bity | od (2 do potęgi -149) do ((2-2 do potęgi -23)*2 do potęgi 127) |
podwójnie | 64 bity | od (-2 do potęgi 63) do ((2 do potęgi 63)-1) |
wartość logiczna | 8 (w przypadku użycia w tablicach), 32 (w przypadku użycia w przypadku innych niż tablice) | prawda czy fałsz |
char
ma zakres liczbowy od 0 do 65536. Ale co to oznacza? W końcu char
są to nie tylko cyfry, ale także litery, znaki interpunkcyjne... Faktem jest, że wartości char
są przechowywane w Javie w formacie Unicode. Z Unicode zetknęliśmy się już w jednym z poprzednich wykładów. Prawdopodobnie pamiętasz, że Unicode to standard kodowania znaków, który obejmuje znaki z prawie wszystkich pisanych języków świata. Innymi słowy, jest to lista kodów specjalnych, w której znajduje się kod dla prawie dowolnego znaku z dowolnego języka. Ogólna tabela Unicode jest bardzo duża i oczywiście nie trzeba się jej uczyć na pamięć. Oto na przykład fragment: Najważniejsze jest, aby zrozumieć zasadę przechowywania wartości char
i pamiętać, że znając kod konkretnego symbolu, zawsze możesz go uzyskać w programie. Spróbujmy tego z jakąś losową liczbą:
public static void main(String[] args) {
int x = 32816;
char c = (char) x ;
System.out.println(c);
}
Dane wyjściowe konsoli: 耰 To jest format, w jakim znaki są przechowywane w Javie char
. Każdy znak odpowiada liczbie - kodowi numerycznemu składającemu się z 16 bitów lub dwóch bajtów. Unicode 32816 odpowiada znakowi 耰. Zwróć uwagę na ten moment. W tym przykładzie użyliśmy zmiennej int
. Zajmuje 32 bity pamięci , natomiast char
16 . Tutaj wybraliśmy , ponieważ potrzebny nam numer 32816 jest poza zakresem . Chociaż rozmiar , podobnie jak krótki, wynosi 16 bitów, w zakresie nie ma liczb ujemnych, więc zakres „dodatni” jest dwukrotnie większy (65536 zamiast 32767 ). Możemy użyć , o ile nasz kod mieści się w zakresie 65536. Ale jeśli utworzymy liczbę , zajmie ona więcej niż 16 bitów. A zawężając typy: int
short
char
char
char
short
int
int >65536
char c = (char) x;
dodatkowe bity zostaną odrzucone, a wynik będzie zupełnie nieoczekiwany.
Funkcje dodawania znaków char i liczb całkowitych
Spójrzmy na ten niezwykły przykład:public class Main {
public static void main(String[] args) {
char c = '1';
int i = 1;
System.out.println(i+c);
}
}
Wyjście konsoli: 50 O_O Gdzie jest logika? 1+1, skąd się wzięło 50?! Wiesz już, że wartości char
przechowywane są w pamięci jako liczby z zakresu od 0 do 65536, reprezentujące Unicode naszej postaci. Więc oto jest. Kiedy wykonujemy dodawanie, char
a jakiś typ liczby całkowitej char
jest konwertowany na liczbę, która mu odpowiada w Unicode. Kiedy w naszym kodzie dodaliśmy 1 i 1, symbol 1 został przekształcony w jego kod, który wynosi 49 (możesz to sprawdzić w tabeli powyżej). Zatem wynik wyniósł 50. Weźmy jeszcze raz naszego starego znajomego za przykład i spróbujmy go dodać z jakąś liczbą.
public static void main(String[] args) {
char c = '耰';
int x = 200;
System.out.println(c + x);
}
Wyjście z konsoli: 33016 Już dowiedzieliśmy się, że odpowiada kodowi 32816. A gdy dodamy tę liczbę do 200, otrzymamy dokładnie nasz wynik - 33016 :) Mechanizm działania, jak widać, jest dość prosty.
GO TO FULL VERSION