Почему Java + =, - =, * =,/= оператора присваивания присваивания не требуют кастинга?
До сегодняшнего дня я думал, что, например:
i += j;
Был просто ярлык для:
i = i + j;
Но если мы попробуем это:
int i = 5;
long j = 8;
Тогда i = я + j;
не будет компилироваться, но i += j;
будет компилировать штраф.
Означает ли это, что на самом деле i += j;
является ярлыком для чего-то вроде этого i = (type of i) (i + j)
?
Ответы
Ответ 1
Как всегда с этими вопросами, 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);
Другими словами, ваше предположение верно.
Ответ 2
Хорошим примером этой отливки является использование * = или /=
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'
Ответ 3
Очень хороший вопрос. Спецификация Java Language подтверждает ваше предложение.
Например, следующий код верен:
short x = 3;
x += 4.6;
и приводит к тому, что x имеет значение 7, потому что оно эквивалентно:
short x = 3;
x = (short)(x + 4.6);
Ответ 4
Да,
в основном, когда мы пишем
i += l;
компилятор преобразует это значение в
i = (int)(i + l);
Я только что проверил код файла .class
.
Действительно хорошая вещь, чтобы знать
Ответ 5
вам нужно сделать от 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.
но в случае +=
он просто отлично работает, потому что оператор неявно выполняет литье типов из типа правой переменной в тип левой переменной, поэтому не нужно явно указывать.
Ответ 6
Проблема здесь связана с литьем типов.
Когда вы добавляете int и long,
- Объект int заносится в long и оба добавляются, и вы получаете длинный объект.
- но длинный объект не может быть неявным образом передан в int. Итак, вы должны сделать это явно.
Но +=
закодирован таким образом, что он набирает тип. i=(int)(i+m)
Ответ 7
В преобразованиях типа Java выполняется автоматически, когда тип выражения в правой части операции присваивания можно безопасно продвигать к типу переменной в левой части задания. Таким образом, мы можем смело назначить:
byte -> short -> int -> long -> float -> double.
То же самое не будет работать наоборот. Например, мы не можем автоматически преобразовать long в int, потому что первое требует большего объема памяти, чем второе, и, следовательно, информация может быть потеряна. Чтобы заставить такое преобразование, мы должны выполнить явное преобразование.
Тип - Конверсия
Ответ 8
Иногда такой вопрос можно задать на собеседовании.
Например, когда вы пишете:
int a = 2;
long b = 3;
a = a + b;
нет автоматического приведения типов. В С++ не будет никакой ошибки компиляции вышеуказанного кода, но в Java вы получите что-то вроде Incompatible type exception
.
Чтобы избежать этого, вы должны написать свой код следующим образом:
int a = 2;
long b = 3;
a += b;// No compilation error or any exception due to the auto typecasting
Ответ 9
Основное отличие состоит в том, что с 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);
Ответ 10
Тонкий момент здесь...
Существует неявная i+j
для i+j
когда j
является двойным, а i
является целым числом. Java ВСЕГДА преобразует целое число в двойное, когда между ними есть операция.
Чтобы уточнить i+=j
где i
- целое число, а j
- двойное, его можно описать как
i = <int>(<double>i + j)
Смотрите: это описание неявного приведения
В этом случае вы можете указать тип j
в (int)
для ясности.
Ответ 11
Спецификация языка Java определяет E1 op= E2
чтобы быть эквивалентным E1 = (T) ((E1) op (E2))
где T
- это тип E1
а E1
оценивается один раз.
Это технический ответ, но вам может быть интересно, почему это так. Хорошо, давайте рассмотрим следующую программу.
public class PlusEquals {
public static void main(String[] args) {
byte a = 1;
byte b = 2;
a = a + b;
System.out.println(a);
}
}
Что печатает эта программа?
Вы догадались 3? Жаль, что эта программа не скомпилируется. Зачем? Что ж, бывает так, что добавление байтов в Java определено как возвращающее int
. Я полагаю, это произошло потому, что виртуальная машина Java не определяет байтовые операции для сохранения в байтовых кодах (в конце концов, их число ограничено), а использование целочисленных операций - это деталь реализации, представленная на языке.
Но если a = a + b
не работает, это будет означать, что a += b
никогда не будет работать для байтов, если его E1 += E2
определено как E1 = E1 + E2
. Как показывает предыдущий пример, это действительно так. В качестве хака для того, чтобы оператор +=
работал для байтов и шортов, подразумевается неявное приведение. Это не так здорово, но во время работы над Java 1.0 основное внимание уделялось выпуску языка с самого начала. Теперь, из-за обратной совместимости, этот хак, введенный в Java 1.0, не может быть удален.
Ответ 12
В случае оператора оператора присваивания выполняется автоматический запуск внутреннего типа:
byte b1 = 10;
//b1 = b1 + 1; Compile time error because found int
System.out.println(b1);
byte b3 = 10;
b3 += 1; //in compound assignment implicit type casting will be performed simultaneously
System.out.println("b3=: "+b3);
byte b4 = 127;
b4 += 3; //in compound assignment implicit type casting will be performed simultaneously
System.out.println("b4=: "+b4);//-126
И в некоторых случаях вы потеряете некоторые значения:
int i = 1;
i += 1.5;
System.out.println("i=: "+i); //will print 2, and you lost .5 !!!