здрасти Докато сте напредвали в CodeGym, много пъти сте срещали примитивни типове. Ето кратък списък на това, което знаем за тях:
- Те не са обекти и представляват стойност, съхранена в паметта
- Има няколко вида
- Цели числа: byte , кратко , int , дълго
- Числа с плаваща запетая (дробни): float и double
- Логически стойности: булеви
- Символни стойности (за представяне на букви и цифри): char
-
Всеки тип има свой собствен диапазон от стойности:
Примитивен тип |
Размер в паметта |
Диапазон на стойността |
byte |
8 бита |
-128 до 127 |
къс |
16 бита |
-32768 до 32767 |
въглен |
16 бита |
0 до 65536 |
вътр |
32 бита |
-2147483648 до 2147483647 |
дълго |
64 бита |
-9223372036854775808 до 9223372036854775807 |
плавам |
32 бита |
(2 на степен -149) на ((2 - (2 на степен -23)) * 2 на степен 127) |
двойно |
64 бита |
(-2 на степен 63) до ((2 на степен 63) - 1) |
булево |
8 (когато се използва в масиви), 32 (ако не се използва в масиви) |
истина or лъжа |
Но освен че имат различни стойности, те се различават и по това колко място заемат в паметта. Int отнема повече от един byte
. И
дългото е по-голямо от късото. Размерът на паметта, зает от примитивите, може да се сравни с руските кукли за гнездене:
![Разширяване и стесняване на примитивните типове - 2]()
всяка кукла за гнездене има свободно място вътре. Колкото по-голяма е куклата, толкова повече място има. Голяма кукла за гнездене (
дълга ) ще побере лесно по-малка
вътр . Лесно се побира и не е необходимо да правите нищо друго. В Java, когато работите с примитиви, това се нарича имплицитно преобразуване. Или казано по друг начин, това се нарича разширяване.
Разширяване в Java
Ето прост пример за разширяващо се преобразуване:
public class Main {
public static void main(String[] args) {
int bigNumber = 10000000;
byte littleNumber = 16;
bigNumber = littleNumber;
System.out.println(bigNumber);
}
}
Тук присвояваме byteова стойност на
int променлива. Присвояването е успешно без ниHowви проблеми: стойността, съхранена в byte, заема по-малко памет от това, което
int може да побере. Малката кукла за гнездене (byteова стойност) лесно се побира в голямата кукла ( променлива
int ). Друг е въпросът, ако се опитате да направите обратното, т.е. да поставите голяма стойност в променлива, чийто обхват не може да побере такъв голям тип данни. С истински кукли за гнездене броят просто не би се поместил. С Java може, но с нюанси. Нека опитаме да поставим
int в
кратка променлива:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = bigNumber;
System.out.println(bigNumber);
}
грешка! Компилаторът разбира, че се опитвате да направите нещо необичайно, като пъхнете голяма кукла (
int ) в малка (
short ). В този случай грешката при компorране е предупреждение от компилатора: "Хей,
абсолютно сигурни ли сте , че искате да направите това?" Ако сте сигурни, тогава казвате на компилатора:
"Всичко е наред. Знам Howво правя!" Този процес се нарича явно преобразуване на типа or стесняване.
Стесняване в Java
За да извършите стесняващо преобразуване, трябва изрично да посочите типа, към който искате да конвертирате вашата стойност. С други думи, трябва да отговорите на въпроса на компилатора:
"Е, в коя от тези малки кукли искате да поставите тази голяма кукла?" В нашия случай изглежда така:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = (short) bigNumber;
System.out.println(littleNumber);
}
Ние изрично посочваме, че искаме да поставим
int в променлива
short и че ще поемем отговорността. Виждайки, че по-тесен тип е изрично указан, компилаторът извършва преобразуването. Howъв е резултатът Изход за конзолата:
-27008 Това беше малко неочаквано. Защо точно получихме това? Всъщност всичко е много просто. Първоначално стойността беше 10000000. Беше съхранена в
int променлива, която заема 32 бита. Това е неговото двоично представяне:
Записваме тази стойност в
кратка променлива, която може да съхранява само 16 бита! Съответно само първите 16 бита от нашето число ще бъдат преместени там. Останалите ще бъдат изхвърлени. В резултат на това променливата short получава следната стойност
което в десетична форма е равно на -27008 Ето защо компилаторът ви моли да "потвърдите", като посочите изрично стесняващо преобразуване към конкретен тип. Първо, това показва, че поемате отговорност за резултата. И второ, той казва на компилатора колко място да разпредели, когато се случи конвертирането. В края на краищата, в последния пример, ако присвоим int стойност на byteова променлива, а не на
short , тогава ще имаме само 8 бита на наше разположение, а не 16, и резултатът ще бъде различен. Дробните типове (
float и
double ) имат собствен процес за стесняване на преобразувания. Ако се опитате да преобразувате фракционно число към тип цяло число, дробната част ще бъде отхвърлена.
public static void main(String[] args) {
double d = 2.7;
long x = (int) d;
System.out.println(x);
}
Конзолен изход:
2
въглен
Вече знаете, че
char се използва за показване на отделни знаци.
public static void main(String[] args) {
char c = '!';
char z = 'z';
char i = '8';
}
Но този тип данни има няколко характеристики, които е важно да разберете. Нека отново да разгледаме tableта със стойностни диапазони:
Примитивен тип |
Размер в паметта |
Диапазон на стойността |
byte |
8 бита |
-128 до 127 |
къс |
16 бита |
-32768 до 32767 |
въглен |
16 бита |
0 до 65536 |
вътр |
32 бита |
-2147483648 до 2147483647 |
дълго |
64 бита |
-9223372036854775808 до 9223372036854775807 |
плавам |
32 бита |
(2 на степен -149) на ((2 - (2 на степен -23)) * 2 на степен 127) |
двойно |
64 бита |
(-2 на степен 63) до ((2 на степен 63) - 1) |
булево |
8 (когато се използва в масиви), 32 (ако не се използва в масиви) |
истина or лъжа |
Диапазонът от 0 до 65536 е посочен за типа
char . Но Howво означава това? В края на краищата,
char не представлява само числа, но и букви, препинателни знаци... Работата е там, че в Java стойностите
на char се съхраняват във формат Unicode. Вече се сблъскахме с Unicode в един от предишните уроци. Вероятно си спомняте, че Unicode е стандарт за codeиране на знаци, който включва символите на почти всички писмени езици по света. С други думи, това е списък от специални codeове, които представляват почти всеки знак на всеки език. Цялата Unicode table е много голяма и, разбира се, няма нужда да я учите наизуст. Ето малка част от него:
![Разширяване и стесняване на примитивни типове - 5]()
Основното нещо е да разберете How се съхраняват символите и да запомните, че ако знаете codeа за конкретен символ, винаги можете да създадете този знак във вашата програма. Нека опитаме с произволно число:
public static void main(String[] args) {
int x = 32816;
char c = (char) x ;
System.out.println(c);
}
Конзолен изход: 耰 Това е форматът, използван за съхраняване на
символи в Java. Всеки символ съответства на число: 16-битов (двуbyteов) цифров code. В Unicode 32816 съответства на китайския знак 耰. Обърнете внимание на следната точка. В този пример използвахме
int променлива. Той заема 32 бита в паметта, докато
char заема 16. Тук избрахме
int , защото нашето число (32816) няма да се побере в
short . Въпреки че размерът на
char (точно като
short ) е 16 бита, няма отрицателни числа в диапазона
char , така че "положителната" част на
charобхватът е два пъти по-голям (65536 instead of 32767 за
късия тип). Можем да използваме
int , докато codeът ни остане под 65536. Но ако създадете
int стойност, по-голяма от 65536, тогава тя ще заема повече от 16 бита. И това ще доведе до стесняващо преобразуване
char c = (char) x;
допълнителните битове ще бъдат изхвърлени (Howто беше обсъдено по-горе) и резултатът ще бъде доста неочакван.
Специални характеристики на добавяне на знаци и цели числа
Нека да разгледаме един необичаен пример:
public class Main {
public static void main(String[] args) {
char c = '1';
int i = 1;
System.out.println(i + c);
}
}
Конзолен изход:
50 O_О Какъв смисъл има това? 1+1. Откъде се взеха 50-те?! Вече знаете, че
char
стойностите се съхраняват в паметта като числа в диапазона от 0 до 65536 и че тези числа са Unicode представяне на знак.
![Разширяване и стесняване на примитивни типове - 6]()
Когато добавим
char и няHowъв тип цяло число,
char се преобразува в съответното Unicode число. В нашия code, когато добавихме 1 и '1', символът '1' беше преобразуван в собствен code, който е 49 (можете да проверите това в tableта по-горе). Следователно резултатът е 50. Нека отново вземем нашия стар приятел 耰 като пример и опитайте да го добавите към няHowво число.
public static void main(String[] args) {
char c = '耰';
int x = 200;
System.out.println(c + x);
}
Конзолен изход:
33016 Вече открихме, че 耰 съответства на 32816. И когато добавим това число и 200, получаваме нашия резултат: 33016. :) Както можете да видите, алгоритъмът тук е доста прост, но не бива да го забравяте .