Почему нет необходимости явно приводить в случае целых чисел? - PullRequest
3 голосов
/ 24 июня 2019
byte a=10;
byte b=20;

b=a+b;

В этом случае мне нужно явно преобразовать a+b в байт следующим образом:

b=(byte)(a+b);

То же самое с коротким:

short x=23;
short y=24;

В противном случае выдает ошибку.

Но в случае целых чисел преобразование не требуется:

int p=7788;
int q=7668;

p=p+q;

Это будет отлично работать.

Почему это?

Нам не нужно явно приводить даже в случае long.

Ответы [ 3 ]

7 голосов
/ 24 июня 2019

Если вы посмотрите на JLS 4.2.2 Операции с целыми числами , в нем говорится, что результатом числовой операции между двумя целыми операндами является int или long. Поскольку не существует неявного приведения от int к byte или short, вам необходимо явное приведение.

3 голосов
/ 24 июня 2019

Если вы ссылаетесь на JLS Sec 15.18.2 , в котором рассматривается добавление числовых типов, то в нем говорится:

Двоичное числовое продвижение выполняется над операндами (§5.6.2).

...

Типом аддитивного выражения числовых операндов является продвинутый тип его операндов.

JLS Sec5.6.2 описывает двоичное числовое продвижение :

  1. Если какой-либо операнд имеет ссылочный тип, он подвергается преобразованию без распаковки (§5.1.8).

  2. Преобразование растущего примитива (§5.1.2) применяется для преобразования одного или обоих операндов, как указано в следующих правилах:

    • Если один из операндов имеет тип double, другой преобразуется в двойной.

    • В противном случае, если один из операндов имеет тип float, другой преобразуется в float.

    • В противном случае, если один из операндов имеет тип long, другой преобразуется в long.

    • OtheВ противном случае оба операнда преобразуются в тип int.

Так, в случае int и long (где оба операнда имеютэтот тип), двоичное числовое продвижение является недопустимым: операнды остаются int и long соответственно, а результат добавления - int и long соответственно, то есть результат может быть назначен переменнымэтот тип.

В случае byte и short двоичное числовое продвижение приводит к расширению обоих из них до int для выполнения сложения, и результат сложения равен int;Вы должны явно привести обратно к более узкому типу, потому что не все значения int вписываются в byte или short.


Из этого требования есть 2 исключения для выполнения явного

Во-первых, составные назначения: это сработало бы:

b += a;

, потому что, как указано в JLS Sec 15.26.2 :

Составное выражение присваивания в форме E1 op= E2 эквивалентно E1 = (T) ((E1) op (E2)), где T - это тип E1, за исключением того, что E1 вычисляется только один раз.

Другими словами: компилятор вставляет приведение для вас:

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

Во-вторых, если операнды имеют постоянные значения и известно, что результат сложения вписывается в диапазон более узкого типа, и вы выполняете присваивание в объявлении переменной.

Например:

final byte a=10;  // final is necessary for a and b to be constant expressions.
final byte b=20;

byte c = a + b;

Это не требует приведения.

2 голосов
/ 24 июня 2019

С добавлением в java, java переведет меньший тип данных в больший. И когда тип данных меньше, чем int, он переводит оба операнда в int. Взгляните на: Продвижение на Яве?

...