Обычно считается, что предварительная позиция ++ сначала добавляет значение переменной к 1, а затем использует значение после добавления 1 для участия в операции; в то время как Post-Position ++ сначала использует значение для участия в операции, а затем добавляет значение к 1.
Давайте посмотрим на первый пример:
Пакет Test; public class plus_test01 {public static void main (string [] args) {int i = 100; i = i ++; System.out.println (i); }}Угадай, каков результат?
Давайте посмотрим на второй:
Пакет Test; Public Class Plus_test02 {public static void main (string [] args) {int k = 100; while (true) {if (k ++> 100) {// System.out.println (k); перерыв; } System.out.println (k); }}}Угадай, каков результат?
Фактически, будь то pre-++ или post-++, значение переменной сначала увеличивается на 1, прежде чем продолжить рассчитать. Реальная разница между этими двумя: pre-++ добавляет значение переменной на 1 и использует добавленное значение для выполнения вычислений, в то время как Post-++ сначала присваивает переменную временную переменную, затем добавляет 1 к значению переменной, а затем использует эту временную переменную для выполнения вычислений.
Для следующего фрагмента кода (префикс ++):
int i = 1;
int j = ++ i*5;
На самом деле, второе предложение эквивалентно:
i+= 1; // Добавить I в 1
j = i*5; // Рассчитайте значение после добавления 1 с ним, результат: 10
И для следующего фрагмента кода (post-++):
int i = 1;
int j = i ++*5;
Второе предложение эквивалентно:
int temp = i; // назначить I на временную переменную
i+= 1; // Добавить I в 1
J = TEMP*5; // Рассчитайте временную переменную с ней, результат: 5
Для первого примера это эквивалентно:
int temp = i;
i+= 1;
я = темп; //
Таким образом, результат должен быть неизменным, то есть 100.
Код сборки для первого примера:
Public Static Void Main (java.lang.string []); дескриптор: ([ljava/lang/string;) V Флаги: acc_public, acc_static код: стек = 2, локалы = 2, args_size = 1 0: bipush 100 2: istore_1 3: iload_1 4: iinc 1, 1 // Второй в локальном var plus 1 7: istore_1 // save to local war 8: getstatic #16 // java/lang/system.out: ljava/io/printstream; 11: Iload_1 // Загруженный параметр является вторым в стеке, то есть он все еще 100 12: Invokevirtual #22 // Метод Java/io/printStream.println: (i) v 15: return
Для второго примера это на самом деле не сложно, но результат - 101. Обратите внимание на процесс, и вы не можете совершать такие ошибки в будущем. (Процесс: сначала сравните temp = i, temp> 100, очевидно, не держит истинную. Пропустите I+= 1 с предложением SYSO, конечно, печати 101, петля снова, и есть также Temp = I, Temp> 100, на этот раз это правда, а затем i+= 1, выпрыгивает из петли напрямую, и заявление, пока не будет выполнено).
Компиляция второго примера (выбран только основной метод):
Public Static Void Main (java.lang.string []); Descriptor: ([ljava/lang/string;) V Флаги: acc_public, acc_static код: стек = 2, локалы = 2, args_size = 1 0: bipush 100 // 100 push stack 2: istore_1 // Сохранить во второй локальный вар (первый локальный вар. Параметр 3: Iload_1 // Нагрузка 4 от второго локального варика: ININC 1, 1, 1, 1, 1, 1, 1, 1// Из локального VAR (локальная переменная увеличивается, результат все еще находится в локальном VAR, верхний 1 из стека операнда не изменится) 7: Bipush 100 // 100 Push Stack 9: if_icmple 15 // Сравните два значения INT Integer в верхней части стека операнде 2) 15: GetStatic #2 // Полевой java/lang/system.out: ljava/io/printstream; 18: iload_1 // // загрузка с первого локального VAR 19: InvokeVirtual #3 // Метод Java/io/printStream.println: (i) v // Вызовите этот метод 22: goto 3 // Прыгайте обратно 3, цикл снова 25: return // Exit Exit
Третий пример:
Пакет -тест; public class plus_test03 {static int proplus () {int i = 55; int j = ++ i; вернуть J; // 56} static int postplus () {int i = 55; int j = i ++; вернуть J; // 55} public static void main (string [] args) {system.out.println (proplus ()); // 56 System.out.println (postplus ()); // 55}}Компиляция третьего примера:
static int proplus (); Descriptor: () I Флаги: ACC_STATIC CODE: Stack = 1, локалы = 2, args_size = 0 0: Bipush 55 // 55 Stack 2: ISTORE_0 // Хранение верхней части стека INT в первую локальную var 3: IINC 0, 1 // СОЗВОДИТ Верхняя часть стека является вторым локальным VAR 9: Ireturnstatic int postplus (); Дескриптор: () I Флаги: ACC_STATIC CODE: Stack = 1, локалы = 2, args_size = 0 0: bipush 55 2: ISTORE_0 3: Iload_0 // загрузка в стек 4: IINC 0, 1 // Первый локальный VAR Plus 1 7: ISTORE_1 8: ILOAD_1: IRTETURN
Видно, что разница между фронтом ++ и задней ++ - синяя часть выше (// первая локальная вар плюс 1), которые являются противоположными. Для предшественника число в локальном VAR будет добавлено 1, а затем загружено в стек, в то время как последний будет загружен из локального стека в стек, а затем будет добавлен локальный VAR, что эквивалентно оставлению резервного копирования.
в заключение:
один. Предварительная позиция и пост-позиция ++ сначала добавляют 1 к значению переменной, вместо того, чтобы добавить 1 к предварительному положению ++, а затем вычислять, в то время как после пост-положения ++, а затем вычисляет.
два. Из программного выступления Post-++ сначала назначает переменную временной переменной, затем добавляет значение переменной на 1, а затем использует временную переменную для участия в операции.
три. С точки зрения инструкции значение переменной нажимается на стек перед выполнением инструкции с добавленной стоимостью (IINC). После выполнения инструкции с добавленной стоимостью используется значение, нажатое на стек.
Я надеюсь, что благодаря этой статье я полностью пойму разницу между операциями Pre-Position ++ и постпозицией ++. Спасибо за поддержку этого сайта!