JavaRush /Курси /Java Syntax Zero /Приведення типів у Java

Приведення типів у Java

Java Syntax Zero
Рівень 8 , Лекція 2
Відкрита

1. Приведення типів

Приведення типів в Java

Змінні примітивних типів (за винятком типу boolean) використовуються для зберігання різних типів чисел. І хоч типи змінних завжди незмінні, є місце, де можна проводити перетворення типів. І це місце — присвоєння.

Можна присвоювати один одному змінні різних типів. При цьому значення, взяте зі змінної одного типу, буде перетворене у значення іншого типу і присвоєне другій змінній. У зв'язку з цим можна виділити два види перетворення типів: розширення і звуження.

Розширення типу схоже на перекладання із маленького кошика в великий — операція проходить непомітно і безболісно. Звуження типу — це перекладання із великого кошика в маленький: місця може не вистачити, і щось доведеться викинути.

Ось типи, відсортовані за розміром «кошика»:

Приведення типів в Java 2


2. Розширення типів

Часто може виникнути необхідність присвоїти змінній одного числового типу значення змінної іншого числового типу. Як це зробити?

У Java є 4 цілих типи:

Тип Розмір
byte 1 байт
short 2 байти
int 4 байти
long 8 байтів

Змінній більшого розміру завжди можна присвоювати значення змінних меншого розміру.

Змінній типу long спокійно можна присвоювати змінні типу int, short і byte. Змінній типу int можна присвоювати змінні типу short і byte. Ну і змінній типу short можна присвоювати змінні типу byte.

Приклади:

Код Опис
byte a = 5;
short b = a;
int c = a + b;
long d = c * c;
Цей код прекрасно скомпілюється.

Таке перетворення, від типу меншого розміру до більшого, називається розширенням типу.

А що стосовно дійсних чисел?

З ними все аналогічно — розмір має значення:

Тип Розмір
float 4 байти
double 8 байтів

Змінній типу double можна без проблем присвоїти змінну типу float. А от з цілими типами цікавіше.

Змінній типу float можна присвоїти змінну будь-якого цілого типу. Навіть типу long, довжина якого 8 байтів. А змінній типу double можна присвоїти взагалі що завгодно: змінну будь-якого цілого типу і змінну типу float:

Код Примітка
long a = 1234567890;
float b = a;
double c = a;

b == 1.23456794E9
c == 1.23456789E9

Зверни увагу, що перетворення до дійсного типу може призвести до втрати точності через нестачу значущих цифр.

При перетворенні з цілих чисел у дробові можуть відкидатися найменші частини числа. Але оскільки сенс дробового числа в тому, щоб зберігати приблизне значення, таке присвоєння дозволяється.


3. Звуження типів

А що щодо інших варіантів? Що робити, якщо потрібно змінній типу int присвоїти значення змінної типу long?

Уявіть, що змінна — це кошик. У нас є кошики різних розмірів: 1, 2, 4 і 8 байт. При перекладанні пиріжків із меншого кошика у більший проблем не буде. А ось при перекладанні з більшого в менший частина пиріжків може загубитися.

Це перетворення — від типу більшого розміру до меншого — називають звуженням типу. При такому присвоєнні частина числа може просто не вміститися в нову змінну й «залишитися за бортом».

При звуженні типу ми маємо явно показати компілятору, що ми не помилилися, і відкидання частини числа зроблене усвідомлено. Для цього використовується оператор приведення типу. Це ім'я типу в круглих дужках.

У таких ситуаціях Java-компілятор вимагає від програміста вказувати оператор перетворення типу. Загалом він виглядає так:

(тип) вираз

Приклади:

Код Опис
long a = 1;
int b = (int) a;
short c = (short) b;
byte d = (byte) c;
Кожного разу потрібно явно вказувати оператор перетворення типу

У цьому випадку a дорівнює 1, і це здається надмірним. А що, якби a було більше?

Код Опис
long a = 1000000;
int b = (int) a;
short c = (short) b;
byte d = (byte) c;
a == 1000000
b == 1000000
c == 16960
d == 64

Мільйон чудово вміщується і в тип long, і в тип int. А ось при присвоєнні мільйона змінній типу short два перших байти були відкинуті, і залишилися тільки два останні байти. А при присвоєнні типу byte взагалі залишився один останній байт.

Устрій чисел у пам'яті:

Тип Двійковий запис Десятковий запис
int 0b00000000000011110100001001000000 1,000,000
short 0b0100001001000000 16,960
byte 0b01000000 64

Тип char

Тип char, як і тип short, займає два байти, але для їх перетворення одного в одного завжди потрібно використовувати оператор приведення типу. Усе тому, що тип short знаковий, і може зберігати значення від -32,768 до +32,767, а тип char беззнаковий, і може зберігати значення від 0 до 65,535.

У char не можна зберегти від'ємні числа, які можуть зберігатися в short. А в short не можна зберегти числа більше 32,767, які можуть зберігатися в char.


4. Тип виразу

А що робити, якщо в одному виразі використовуються змінні різних типів? Логічна відповідь – їх спочатку потрібно перетворити до загального типу. Але до якого?

Звичайно ж, до більшого.

У Java завжди відбувається перетворення до типу більшого розміру. Грубо кажучи, спочатку відбувається розширення типу одного з учасників операції, а вже потім операція зі значеннями однакових типів.

Якщо у виразі беруть участь типи int та long, значення типу int буде перетворено до типу long і лише потім братиме участь в операції:

Код Опис
int a = 1;
long b = 2;
long c = a + b;
a буде розширено до типу long і тільки тоді відбудеться додавання.

Числа з плаваючою точкою

Якщо у виразі беруть участь ціле число і число з плаваючою точкою (float/double), ціле число буде перетворено в число з плаваючою точкою (float/double) і тільки потім буде виконано операцію над ними.

Якщо в операції беруть участь float та double, то float буде перетворено до double. Що, власне, очікувано.

Сюрприз

Типи byte, short, char завжди перетворюються в тип int при взаємодії між собою. Не дарма ж тип int вважається стандартним цілочисельним типом.

Якщо перемножити byte на short, буде int. Якщо перемножити byte на byte, буде int. Навіть якщо скласти byte і byte, буде int.

Причин цьому декілька. Приклади:

Код Опис
byte a = 110;
byte b = 120;
byte c = a * b;   // помилка
110 * 120 буде 13,200, що дещо більше, ніж максимальне значення типу byte: 127
byte a = 110;
byte b = 120;
byte c = a + b;   // помилка
110 + 120 буде 230, що також дещо більше, ніж максимальне значення типу byte: 127

У загальному випадку при множенні числа довжиною в 8 біт (1 байт) на число довжиною в 8 біт (1 байт), ми отримаємо число довжиною 16 біт (2 байти)

Тому всі операції з цілочисельними типами, меншими ніж int, завжди одразу перетворюються в тип int. І тому якщо ви захочете зберегти результат обчислення в змінну типу, меншого ніж int, вам завжди потрібно буде явно вказувати операцію приведення типу.

Приклади:

Код Опис
byte a = 110;
byte b = 120;
byte c = (byte) (a * b);
вираз byte * byte буде мати тип int
byte a = 110;
byte b = 120;
byte c = (byte) (a + b);
вираз byte + byte буде мати тип int
byte a = 1;
byte b = (byte) (a + 1);
вираз byte + int буде мати тип int
одиниця – це літерал типу int.

5. Важливий нюанс

Операція приведення типу має доволі високий пріоритет.

Тому, якщо у виразі є, скажімо, додавання та операція приведення типу, вона буде виконана перед додаванням.

Приклад:

Код Опис
byte a = 1;
byte b = 2;
byte c = (byte) a * b;
Оператор приведення типу буде застосований лише до змінної a, яка й так має тип byte. Код не скомпілюється.
byte a = 1;
byte b = 2;
byte c = (byte) (a * b);
Ось так правильно.

Якщо ви хочете перетворити до певного типу увесь вираз, а не лише один його елемент, то обгорніть увесь вираз у круглі дужки та перед ними поставте оператор приведення типу.


Коментарі (8)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Potapchuk Рівень 13
2 вересня 2023
В задачі "Правильні типи" при написанні byte a = .... short b =... int c = ... вказавши вірну відповідь, результат не зараховується =(. потрібно вказувати а = () ....!
Valentyn Рівень 10
10 серпня 2025
Тому що ці статичні змінні вже оголошені у класі.
Kostiantyn Bogatyrchuk Рівень 14 Expert
22 січня 2023
"Навіть якщо скласти число типу byte і число типу byte, знову таки отримаємо число типу int." mb додати? Javarash потребеє українськомовних редачів? 😅
Василь Рівень 4
24 липня 2023
напишіть в підтримку. Вкажіть місце помилки і лінк на статтю де є помилка. Я так роблю і вони все змінюють.
Pan Vitali Moroz Рівень 51
13 вересня 2022
У програмистів стрінгі утворюються з чарів а у жінок чари зі стрингів...
3 жовтня 2022
😅
Roma Chernesh Рівень 16
19 грудня 2022
0_о
Kostiantyn Bogatyrchuk Рівень 14 Expert
22 січня 2023
🤣👍