До сегодняшнего дня я думал что например
i += j;
Был просто ярлык для:
i = i + j;
Но если мы попробуем это:
int i = 5;
long j = 8;
Тогда i = i + j;
не скомпилирует но i += j;
скомпилирует нормально.
Значит ли это, что на самом деле i += j;
это ярлык для чего-то подобного
i = (type of i) (i + j)
?
java
casting
operators
variable-assignment
assignment-operator
Хонза Брабек
источник
источник
i+=(long)j;
даже скомпилирует нормально.i += (int) f;
бросает f перед сложением, так что это не эквивалентно.(int) i += f;
бросает результат после присваивания, также не эквивалентный. не было бы места для приведения, которое указывало бы на то, что вы хотите привести значение после добавления, но перед присваиванием.Ответы:
Как всегда с этими вопросами, JLS держит ответ. В этом случае §15.26.2 Составные операторы присваивания . Выписка:
Пример, приведенный в §15.26.2
Другими словами, ваше предположение верно.
источник
i+=j
компилирует, как я проверял сам, но это приведет к потере точности, верно? Если это так, то почему это не происходит в i = i + j? Зачем нас там пугать?i += j
) безопаснее предположить, что потеря точности желательна, а не в другом случае (i = i + j
)E1 op= E2 is equivalent to E1 = (T)((E1) op (E2))
это похоже на неявное приведение типа вниз (от long к int). В то время как в i = i + j мы должны сделать это явно, то есть предоставить(T)
часть вE1 = ((E1) op (E2))
Не так ли?Хорошим примером этого кастинга является использование * = или / =
или
или
или
источник
A
;)ch += 32
= DОчень хороший вопрос Спецификация языка Java подтверждает ваше предложение.
источник
double->float
как расширяющиеся, исходя из того, что значения типаfloat
идентифицируют действительные числа менее конкретно, чем значения типаdouble
. Если рассматриватьdouble
полный почтовый адрес иfloat
пятизначный почтовый индекс, можно удовлетворить запрос на почтовый индекс с полным адресом, но невозможно точно указать запрос на полный адрес, используя только почтовый индекс , Преобразование адреса улицы в почтовый индекс - операция с потерями, но ...float->double
эквивалентно преобразованию почтового индекса США 90210 в «Почтовое отделение США, Беверли-Хиллз, Калифорния 90210».Да,
в основном, когда мы пишем
компилятор преобразует это в
Я только что проверил
.class
код файла.Действительно хорошая вещь, чтобы знать
источник
вам нужно привести из
long
кint
explicitly
в случае, еслиi = i + l
он скомпилируется и даст правильный вывод. подобноили
но в случае
+=
этого просто работает нормально, потому что оператор неявно выполняет приведение типа от типа правой переменной к типу левой переменной, поэтому нет необходимости явного приведения.источник
int
выполняются после+
. Компилятор будет (должен?) Выдавать предупреждение, если он действительно приведётlong
кint
.Проблема здесь заключается в приведении типов.
Когда вы добавляете int и long,
Но
+=
закодирован таким образом, что он выполняет приведение типов.i=(int)(i+m)
источник
В Java преобразования типов выполняются автоматически, когда тип выражения в правой части операции присваивания можно безопасно преобразовать в тип переменной в левой части присваивания. Таким образом мы можем смело назначать:
То же самое не будет работать наоборот. Например, мы не можем автоматически преобразовать long в int, потому что первое требует больше памяти, чем второе, и, следовательно, информация может быть потеряна. Чтобы вызвать такое преобразование, мы должны выполнить явное преобразование.
Тип - Конверсия
источник
long
в 2 раза больше, чемfloat
.float
может содержать все возможныеint
значения, аdouble
не может содержать все возможныеlong
значения.double d=33333333+1.0f;
без жалоб, даже если результат 33333332.0, скорее всего, не будет тем, что предполагалось (кстати, арифметически правильный ответ 33333334.0f будет представлен как либо, такfloat
иint
).Иногда такой вопрос можно задать на собеседовании.
Например, когда вы пишете:
нет автоматической типизации. В C ++ не будет ошибок при компиляции приведенного выше кода, но в Java вы получите что-то подобное
Incompatible type exception
.Поэтому, чтобы избежать этого, вы должны написать свой код следующим образом:
источник
op
использования в C ++ с его использованием в Java. Мне всегда нравится видеть эти мелочи, и я думаю, что они вносят свой вклад в разговор, который часто может быть опущен.Основное различие заключается в том
a = a + b
, что при не происходит типизирование, и поэтому компилятор злится на вас за отсутствие типизации. Но с темa += b
, что он действительно делает, является приведением типовb
к типу, совместимому сa
. Так что если вы делаетеЧто вы на самом деле делаете:
источник
Тонкий момент здесь ...
Существует неявное приведение типов для аргумента,
i+j
когдаj
значение double иi
int. Java ВСЕГДА преобразует целое число в двойное, когда между ними есть операция.Чтобы уточнить,
i+=j
гдеi
находится целое число иj
двойное, можно описать какСмотрите: это описание неявного приведения
Вы можете типаж ,
j
чтобы(int)
в этом случае для ясности.источник
int someInt = 16777217; float someFloat = 0.0f; someInt += someFloat;
. Добавление к нулюsomeInt
не должно влиять на его стоимость, но продвижениеsomeInt
кfloat
может изменить его значение.Спецификация языка Java определяет,
E1 op= E2
что она эквивалентна типуE1 = (T) ((E1) op (E2))
where и оценивается один разT
E1
E1
.Это технический ответ, но вам может быть интересно, почему это так. Что ж, давайте рассмотрим следующую программу.
Что печатает эта программа?
Вы догадались 3? Жаль, что эта программа не скомпилируется. Почему? Что ж, бывает так, что добавление байтов в Java определено как возвращающее
int
. Я полагаю, это произошло потому, что виртуальная машина Java не определяет байтовые операции для сохранения в байтовых кодах (в конце концов, их число ограничено), а использование целочисленных операций - это деталь реализации, представленная на языке.Но если
a = a + b
не работает, это означалоa += b
бы, что никогда не будет работать для байтов, если этоE1 += E2
было определено какE1 = E1 + E2
. Как показывает предыдущий пример, это действительно так. В качестве хака, заставляющего+=
оператора работать для байтов и шортов, подразумевается неявное приведение. Это не так здорово, но во время работы над Java 1.0 основное внимание уделялось выпуску языка с самого начала. Теперь, из-за обратной совместимости, этот хак, введенный в Java 1.0, не может быть удален.источник