На данный вопрос уже ответили:
Есть код:
int i = 1;
i=i++;
System.out.println(i);
ВНЕЗАПНО
Output:1
Вопрос: Почему выдаёт единицу? Я считаю, что должна дать двойку. Ну и что что постфиксная запись? Даже если оно сначала бы присвоила i
единицу, то потом всё равно должно было увеличить значение i
на единицу.
PS. Мне хочется получить ответ по шагам, типа:
Сначала оно делает это, потому что...
Потом оно делает это, потому что...
Возможно понятнее будет на уровне байткода. Ваш код будет скомпилирован в
0: iconst_1 // Загрузить константу 1 в стек
1: istore_1 // Сохранить значение из стека в локальную переменную i
2: iload_1 // Загрузить значение локальной переменной i в стек (в стеке 1)
3: iinc 1, 1 // Увеличить значение локальной переменной i на 1 (в переменной теперь 2)
6: istore_1 // СОХРАНИТЬ ЗНАЧЕНИЕ ИЗ СТЕКА В ПЕРЕМЕННУЮ i (в переменной опять 1)
7: getstatic #2
10: iload_1 // Загрузить в стек значение переменной i
11: invokevirtual #3 // Вывести значение
Я не нашёл конкретного описания этого поведения в Java Language Specification, но оно не противоречит разделам 15.14.2 и 15.26.1 описывающим порядок разбора выражений постинкремента и присваивания.
int i = 1;
// вместо i = i++;
int __temp = i;
i = i + 1;
i = __temp;
System.out.println(i);
Что происходит в строке
i = i++;
Сначала вычисляется правая часть. Запоминается значение i
(равное 1
). Потом значение i
увеличивается на один. Потом возвращается запомненное значение 1
. Потом выполняется присваивание значения 1
переменной i
.
Это то же самое, что написано в других ответах.
В вашем примере используется post-increment (i++
), в этом случае вы сначала получите старое значение, а уже затем добавите один к текущему значению(++
). Чтобы получить 2 необходимо использовать pre-increment: ++i
(прошу заметить инкремент перед именем переменной).
Вот смотрите, такой код:
int i = 1;
i = i++;
int a = i;
System.out.println(a + "" + i);
int b = i++;
System.out.println(b + "" + i);
выводит
11 // обратите внимание, что i снова вернулось значение 1
12 // i уже равно 2, но b получает старое значение i
то есть, выражение N=i++ действительно увеличивает i на единицу, но переменной N будет присвоено значение, которое было у i до увеличения - по такому закону работает постфикс.
"Изюминка" в вашем вопросе состоит в том, что переменную i вы действительно увеличили на единицу, но потом "внезапно" той же переменной i присвоили значение, которое было до увеличения - и переменная i у вас снова стала равна 1.
Ответ "по шагам": причина такого результата в следующем - сначала делается операция увеличения i на единицу, а потом делается операция присвоения левой переменной значения i, которое было вначале. Если и слева и справа одна и та же переменная, то вторая операция естественно "затирает" все предыдущие операции.
int i = 1; // i=1
i++ // i=2, значение выражения 1
i = ...; // присвоить 1 в переменную i - получается i=1
Дружище для начала надо понять как работает оператор ++ есть
int i = 1;
OperatorPlusPlus(i);
int OperatorPlusPlus(int yourNumber){
int tmp = yourNumber;
int yourNumber = yourNumber + 1;
return tmp;
}
То есть вы получаете значение переменной tmp и i у вас равна 2, далее вы i (2) присваивание значение tmp(1)
Начнём с азов работы инкремента.
Возьмём пример:
int x = 1;
int y = x++;
System.out.println(y +""+x);
Output:12
В первом приближении может казаться, что во второй строчке произошло следующее:
Однако более пристальный взгляд, говорит что всё оказалось гораздо сложнее. Для этого нужно глянуть декомпилированный байт-код этого же примера:
byte x = 1; //int x = 1 - ориг. код
byte var10000 = x; //2 строка ориг. кода
int x1 = x + 1; //2 строка ориг. кода
byte y = var10000; //2 строка ориг. кода
System.out.println(y + "" + x1);
Из него, можно вполне видеть, что эквивалентом "простой" строчки int y = x++;
становятся сразу три строки. Похоже они работают следующим образом:
Далее переменной y присваивается значение var10000 - то есть старого значения x.
Получается, что префиксный инкремент содержит в себе создание двух новых переменных.
Из вышесказанного очевидно, что исходное выражение:
int i = 1;
i=i++;
System.out.println(i);
в декомпилированном байт коде будет выглядеть, как:
byte i = 1; //x заменили на i
byte var10000 = i;
int i1 = i + 1;
i = var10000; //Мы по сути y заменили i
System.out.println(i);
То есть, последняя операция перед выводом на консоль - это запись в переменную i временного значения. В соответствии с приоритетом операций, присваивание всегда выполняется после инкремента\декремента.
PS. Дополнительно, на аналогичный вопрос дали 17! ответов в английском стэковерфлоу.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
В приложении использую прокрутку в Textview с помощью метода ScrollingMovementMethod()Все отлично работает, но очень раздражает, что при нажатии на Textview...
подскажите по UML диаграмме, с трудом понимаю что данное приложение должно делать, если я верно понял то оно должно анализировать выраженияС-класс...
Есть ли возможность в java получить индекс элемента коллекции в цикле foreach?
Давайте соберем подборку хорошей литературы и ресурсов (для разработчиков с разным уровнем владения материалом) по ОС Android (архитектура,...