Почему операторам Java + =, – =, * =, / = сложного присваивания не требуется кастинг?

До сегодняшнего дня я думал, что, например:

i += j; 

это просто ярлык для:

 i = i + j; 

Но что, если мы попробуем это:

 int i = 5; long j = 8; 

Тогда i = i + j; не будет компилироваться, но i += j; будет компилировать штраф.

Означает ли это, что на самом деле i += j; является ярлыком для чего-то вроде этого i = (type of i) (i + j) ?

Как всегда с этими вопросами, JLS держит ответ. В этом случае §15.26.2. Операторы присвоения соединения . Экстракт:

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

Пример, приведенный в п. 15.26.2

[…] правильный код:

 short x = 3; x += 4.6; 

и приводит к тому, что x имеет значение 7, потому что оно эквивалентно:

 short x = 3; x = (short)(x + 4.6); 

Другими словами, ваше предположение верно.

Хорошим примером этого литья является использование * = или / =

 byte b = 10; b *= 5.7; System.out.println(b); // prints 57 

или

 byte b = 100; b /= 2.5; System.out.println(b); // prints 40 

или

 char ch = '0'; ch *= 1.1; System.out.println(ch); // prints '4' 

или

 char ch = 'A'; ch *= 1.5; System.out.println(ch); // prints 'a' 

Очень хороший вопрос. Спецификация языка Java подтверждает ваше предложение.

Например, следующий код верен:

 short x = 3; x += 4.6; 

и приводит к тому, что x имеет значение 7, потому что оно эквивалентно:

 short x = 3; x = (short)(x + 4.6); 

Да,

в основном, когда мы пишем

 i += l; 

компилятор преобразует это в

 i = (int)(i + l); 

Я просто проверил код файла .class .

Действительно хорошая вещь, чтобы знать

вам нужно использовать от long до int explicitly в случае i = i + l тогда он будет компилировать и давать правильный результат. как

 i = i + (int)l; 

или

 i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly. 

но в случае += он просто отлично работает, потому что оператор неявно выполняет литье типов от типа правильной переменной до типа левой переменной, поэтому не нужно явно указывать.

Проблема здесь связана с литьем типов.

Когда вы добавляете int и long,

  1. Объект int заносится в long и оба добавляются, и вы получаете длинный объект.
  2. но длинный объект не может быть неявным образом передан в int. Итак, вы должны сделать это явно.

Но += закодирован таким образом, что он набирает тип. i=(int)(i+m)

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

  byte -> short -> int -> long -> float -> double. 

То же самое не будет работать наоборот. Например, мы не можем автоматически преобразовать long в int, потому что первое требует большего объема памяти, чем второе, и, следовательно, информация может быть потеряна. Чтобы заставить такое преобразование, мы должны выполнить явное преобразование.
Тип – конверсия

Иногда такой вопрос можно задать на собеседовании.

Например, когда вы пишете:

 int a = 2; long b = 3; a = a + b; 

нет автоматического приведения типов. В C ++ не будет никакой компиляции ошибки, описанной выше, но в Java вы получите что-то вроде Incompatible type exception .

Чтобы избежать этого, вы должны написать свой код следующим образом:

 int a = 2; long b = 3; a += b;// No compilation error or any exception due to the auto typecasting 

Основное различие заключается в том, что при a = a + b не происходит никакого приведения типов, и поэтому компилятор сердится на вас за то, что он не типизируется. Но с a += b , что он действительно делает, – это приведение типа b к типу, совместимому с a . Так что если вы это сделаете

 int a=5; long b=10; a+=b; System.out.println(a); 

То, что вы действительно делаете, это:

 int a=5; long b=10; a=a+(int)b; System.out.println(a); 

Тонкая точка здесь …

Существует неявный typecast для i+j когда j является double, а i – int. Java ALWAYS преобразует целое число в double при выполнении операции между ними.

Чтобы прояснить i+=j где i – целое число, а j – двойное, можно описать как

 i = (i + j) 

См. Это описание неявного литья

В этом случае вам может потребоваться приведение типа j к (int) для ясности.

Interesting Posts

Источник впрыска Джерси 2 для многочастных форм

Как включить новый просмотр инспектора 3D-страниц в Firefox 11

Проверьте, попадает ли экземпляр datetime между двумя другими объектами datetime

Java, изменение содержимого ячейки как функции другой ячейки в той же строке

Разница Java между FileWriter и BufferedWriter

Что произойдет, если я установлю больше оперативной памяти, чем указано в руководстве?

Как исправить ошибку «Fail to connect to camera service» в Android-эмуляторе

Удаленные запросы Rails 3.1, отправляемые дважды

По умолчанию SecurityProtocol в .NET 4.5

Как я могу предотвратить копирование файлов в моем USB-накопителе?

Должен ли я создавать резервные копии скрытого раздела в 100 МБ при создании образа диска с помощью Clonezilla?

Требуется ли $ (документ)?

Может ли ноутбук работать на другом зарядном устройстве бренда?

Мониторинг среднего использования ЦП и использования ОЗУ на одном потоке процессов

Скопируйте рабочий лист Excel и поддерживайте относительную ссылку на ячейки в формулах

Давайте будем гением компьютера.