JavaRush/Java блог/Random UA/Приведення (перетворення) примітивних типів у Java

Приведення (перетворення) примітивних типів у Java

Стаття з групи Random UA
учасників
Вітання! Під час проходження JavaRush ти неодноразово стикався з примітивними типами. Ось короткий список того, що ми про них знаємо:
  1. Вони не є об'єктами і є значенням, що зберігається в пам'яті
  2. Примітивні типи бувають кількох видів:
    • Цілі числа - byte, short, int,long
    • Числа з плаваючою точкою (дрібні) - floatіdouble
    • Логічний -boolean
    • Символьний (для позначення букв та цифр)char
  3. Кожен має свій діапазон значень:
Примітивний тип Розмір у пам'яті Діапазон значень
byte 8 біт від -128 до 127
short 16 біт до -32768 до 32767
char 16 біт від 0 до 65536
int 32 біта від -2147483648 до 2147483647
long 64 біта від -9223372036854775808 до 9223372036854775807
float 32 біта від (2 у ступені -149) до ((2-2 у ступені -23)*2 у ступені 127)
double 64 біта від (-2 у ступені 63) до ((2 у ступені 63) - 1)
boolean 8 (при використанні в масивах), 32 (при використанні не в масивах) true або false
Але, крім значень, типи відрізняються ще й розміром у пам'яті. intзаймає більше, ніж byte. А long- більше, ніж short. Об'єм займаної примітивами пам'яті можна порівняти з матрьошками: Розширення та звуження примітивних типів - 2 Усередині матрьошки є вільне місце. Чим більше матрьошка – тим більше місця. Всередину великої матрьошки longми легко можемо покласти меншу за розміром int. Вона легко вміститься, і нічого робити додатково не потрібно. У Java під час роботи з примітивами це називається автоматичним перетворенням. Інакше його називають розширенням. Ось простий приклад розширення:
public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       byte littleNumber = 16;

       bigNumber = littleNumber;
       System.out.println(bigNumber);
   }
}
Тут ми привласнюємо значення byteзмінну int. Привласнення пройшло успішно і без будь-яких проблем: значення, що зберігається в byte, займає менший обсяг у пам'яті, ніж "влазить" в int. "Маленька матрьошка" (значення byte) легко влазить у "велику матрьошку" (змінну int). Інша річ, коли ти намагаєшся зробити навпаки — покласти значення великого розміру в змінну, яка не розрахована на такі розміри. Зі справжніми матрьошками такий номер у принципі не пройде, а в Java — минеться, але з нюансами. Давай спробуємо покласти значення intв змінну short:
public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = bigNumber;//помилка!
   System.out.println(bigNumber);
}
Помилка! Компілятор розуміє, що ти намагаєшся зробити щось нестандартне і засунути велику матрьошку ( int) всередину маленької ( short). Помилка компіляції у разі — попередження від компілятора: “ Гей, ти точно впевнений, що це хочеш? ” Якщо ти певен, говориш про це компілятору: “ Все ок, я знаю, що роблю! ” Цей процес називається явним перетворенням типів, або звуженням . Щоб зробити звуження, тобі необхідно вказати тип, до якого ти хочеш привести своє значення. Іншими словами, відповісти компілятору на його запитання: " Ну і в яку з цих маленьких матрьошок ти хочеш засунути цю велику матрьошку?" ” У нашому випадку це буде виглядати так:
public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = (short) bigNumber;
   System.out.println(littleNumber);
}
Ми явно вказали, що хочемо помістити значення intу змінну shortта беремо відповідальність на себе. Компілятор, бачачи явну вказівку більш вузький тип, проводить перетворення. Яким буде результат? Висновок: -27008 Трохи несподівано. Чому саме такий? Насправді, все просто. У нас було початкове значення - 10000000 Воно зберігалося в змінній int, яка займала 32 біти, і в двійковій формі воно виглядало так: Розширення та звуження примітивних типів - 3 Ми записуємо це значення в змінну short, але вона може зберігати лише 16 біт! Відповідно, лише перші 16 біт нашого числа будуть туди переміщені, решта — відкинуться. У результаті змінну shortпотрапить значення Розширення та звуження примітивних типів - 4Саме тому компілятор “просив підтвердження” у формі явного приведення до конкретного типу. По-перше, воно показує, що ти береш відповідальність за результат на себе, а по-друге, вказує компілятор скільки місця виділити при наведенні типів. Адже якби ми в останньому прикладі приводабо 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

Ти вже знаєш, що тип char використовується для відображення окремих символів.
public static void main(String[] args) {

   char c = '!';
   char z = 'z';
   char i = '8';

}
Але він має ряд особливостей, які важливо розуміти. Давай ще раз подивимося в таблицю з діапазонами значень:
Примітивний тип Розмір у пам'яті Діапазон значень
byte 8 біт від -128 до 127
short 16 біт від -32768 до 32767
char 16 біт від 0 до 65536
int 32 біта від -2147483648 до 2147483647
long 64 біта від -9223372036854775808 до 9223372036854775807
float 32 біта від (2 у ступені -149) до ((2-2 у ступені -23)*2 у ступені 127)
double 64 біта від (-2 у ступені 63) до ((2 у ступені 63)-1)
boolean 8 (при використанні в масивах), 32 (при використанні не в масивах) true або false
Для типу charвказаний числовий діапазон від 0 до 65536. Але що це означає? Адже char— це не лише цифри, а й букви, розділові знаки… Справа в тому, що значення charзберігаються в Java у форматі Юнікоду. Ми вже стикалися з Юнікодом в одній із минулих лекцій. Ти, напевно, пам'ятаєш, що Unicode — це стандарт кодування символів, що включає знаки майже всіх письмових мов світу. Інакше кажучи, це список спеціальних кодів, у якому знайдеться код майже будь-якого символу з мови. Загальна таблиця Юнікод дуже велика, і, звичайно, її не потрібно вчити напам'ять. Ось, наприклад, її шматочок: Розширення та звуження примітивних типів - 5 Головне — розуміти принцип зберігання значень charі пам'ятати, що знаючи код конкретного символузавжди можна отримати його у програмі. Давай спробуємо це зробити з якимось випадковим числом:
public static void main(String[] args) {

   int x = 32816;

   char c = (char) x ;
   System.out.println(c);
}
Висновок в консоль: 耰 Саме в такому форматі Java зберігаються символи char. Кожному символу відповідає число - числовий код розміром 16 біт, або два байти. Юнікоду 32816 відповідає ієрогліф 耰. Зверни увагу на якийсь момент. У цьому прикладі ми використали змінну int. Вона займає в пам'яті 32 біти , тоді як char- 16 . Тут ми вибрали int, тому що потрібне число 32816 знаходиться за межами діапазону short. Хоча розмір char, як і short, дорівнює 16 біт, але в діапазоні charнемає негативних чисел, тому "позитивний" діапазон charвдвічі більше (65536 замість 32767 у short). Ми можемо використовуватиint, Поки наш код вкладається в діапазон до 65536. Але якщо створити число int >65536, воно займатиме більше 16 бітів. І при звуженні типів:
char c = (char) x;
зайві біти будуть відкинуті, і результат буде несподіваним.

Особливості складання char і цілих чисел

Давай розглянемо такий незвичайний приклад:
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, що позначають юнікод нашого символу. Розширення та звуження примітивних типів - 6 Так ось. Коли ми виробляємо додавання charі якогось цілого типу, charперетворюється на число, яке відповідає йому в Юнікоді. Коли в нашому коді ми складали 1 і '1' — символ '1' перетворився на свій код, який дорівнює 49 (можеш перевірити в таблиці вище). Тому результат і дорівнював 50. Давай ще раз візьмемо для прикладу нашого старого друга —, і спробуємо скласти його з якимось числом.
public static void main(String[] args) {

   char c = '耰';
   int x = 200;

   System.out.println(c + x);
}
Висновок в консоль: 33016 Ми вже з'ясували, що відповідає коду 32816. А при складанні цього числа і 200 ми отримуємо якраз наш результат — 33016 :) Механізм роботи, як бачиш, досить простий.
Коментарі
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Для цієї сторінки немає коментарів.