CodeGym /Java блог /Случаен /Разширяване и стесняване на примитивни типове
John Squirrels
Ниво
San Francisco

Разширяване и стесняване на примитивни типове

Публикувано в групата
здрасти Докато сте напредвали в CodeGym, много пъти сте срещали примитивни типове. Ето кратък списък на това, което знаем за тях:
  1. Те не са обекти и представляват стойност, съхранена в паметта
  2. Има няколко вида
    • Цели числа: byte , кратко , int , дълго
    • Числа с плаваща запетая (дробни): float и double
    • Логически стойности: булеви
    • Символни стойности (за представяне на букви и цифри): char
  3. Всеки тип има свой собствен диапазон от стойности:

Примитивен тип Размер в паметта Диапазон на стойността
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;// Error!
   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 бита. Това е неговото двоично представяне:
Разширяване и стесняване на примитивни типове - 3
Записваме тази стойност в кратка променлива, която може да съхранява само 16 бита! Съответно само първите 16 бита от нашето число ще бъдат преместени там. Останалите ще бъдат изхвърлени. В резултат на това променливата short получава следната стойност
Разширяване и стесняване на примитивни типове - 4
което в десетична форма е равно на -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. :) Както можете да видите, алгоритъмът тук е доста прост, но не бива да го забравяте .
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION