Сегодня поговорим о примитивах:


Большинство Java-разработчиков уверены, что прекрасно знают примитивы.
Но есть одна особенность языка, на которой регулярно ошибаются даже опытные разработчики.
Посмотрите на код:



byte a = 10;
byte b = 20;

byte c = a + b;



Как думаете, скомпилируется?
Нет.

Компилятор выдаст ошибку:
incompatible types: possible lossy conversion from int to byte

Но почему? - Ведь мы складываем два byte.

Дело в том, что в Java существует механизм numeric promotion.
При выполнении арифметических операций значения типов byte, short и char автоматически расширяются до int.
То есть выражение:

a + b

фактически имеет тип int, а не byte.
Условно JVM рассматривает это как:

(int) a + (int) b

Получается:

10 + 20 = 30

но результат этого выражения уже является int.
И когда мы пытаемся сделать:

byte c = a + b;

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

byte: -128 ... 127
int: -2147483648 ... 2147483647

Поэтому требуется явное приведение:

byte c = (byte) (a + b);

Но важно понимать:
Это не означает, что все примитивы "под капотом становятся int".

Переменная:

byte value = 10; - остается типа byte.

Расширение происходит только во время выполнения арифметической операции.

Еще один пример:



char ch = 'A';

System.out.println(ch + 1);



Результат:
66

Почему не B?
Потому что char в Java хранит числовое значение Unicode.

Символ:
'A' = 65

Во время вычисления происходит расширение:
(int)'A' + 1

Получаем:
65 + 1 = 66

Поэтому результат — число.

А теперь интересный момент:
Почему этот код компилируется?

char c = 'A';

c += 1;

System.out.println(c);

Вывод:
B
Хотя такой код уже не скомпилируется:

char c = 'A';

c = c + 1;

Почему?
Потому что составной оператор присваивания работает немного иначе.
Выражение:

c += 1;

Java автоматически преобразует примерно в:

c = (char) (c + 1);

То есть внутри происходит:
- char расширяется до int;
- выполняется сложение;
- результат автоматически приводится обратно к типу левой части (char).

А вот в обычном присваивании:

c = c + 1;

результат выражения:

c + 1

имеет тип int.

И Java не делает неявное сужение: int → char

потому что это потенциально может привести к потере данных.

Именно поэтому:

byte b = 1;

b += 1; // работает

b = b + 1; // ошибка компиляции

На первый взгляд оба выражения выглядят одинаково.
Но для Java это разные операции. И такие маленькие детали часто становятся границей между разработчиком, который просто пишет код, и инженером, который понимает, что происходит под капотом.
Просмотры: 93
Открыть в MAX Сообщить о неточности

Репосты публикации

Публикация канала

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти