English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Si considera generalmente che il ++前置 aggiunge prima il valore della variabile e poi utilizza il valore aumentato per l'operazione; mentre il ++postfix utilizza prima il valore per l'operazione e poi lo aumenta.
Ecco un esempio:
package test; public class Plus_Test01 { public static void main(String[] args) { int i = 100; i = i++; System.out.println(i); } }
Indovina qual è il risultato?
Vediamo il secondo:
package test; public class Plus_Test02 { public static void main(String[] args) { int k = 100; while (true) { if (k++ > 100) { // Stampa k; break; } System.out.println(k); } } }
Indovina qual è il risultato?
In realtà, sia il prefix increment che il postfix increment aggiungono prima il valore della variabile, quindi continuano a calcolare. La vera differenza tra i due è che il prefix increment utilizza il valore aumentato della variabile per il calcolo, mentre il postfix increment assegna il valore della variabile a un variabile temporanea, poi aumenta il valore della variabile e utilizza quella variabile temporanea per il calcolo.
Per il seguente segmento di codice (prefix increment):
int i=1;
int j=++i*5;
La seconda frase è equivalente a:
i+=1; //Aggiorna i di 1
j=i*5; //Calcola il valore con il valore aggiornato, questo risultato è: 10
E per il seguente segmento di codice (postfix increment):
int i=1;
int j=i++*5;
La seconda frase è equivalente a:
int temp=i; //Assegna il valore di i a un variabile temporanea
i+=1; //Aggiorna i di 1
j=temp*5; //Calcola il valore del temporaneo, questo risultato è: 5
Per l'esempio numero uno, è equivalente a:
int temp=i;
i+=1;
i=temp; //
Quindi il risultato dovrebbe essere invariato, ovvero 100.
Il codice assembly dell'esempio numero uno è:
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Codice: stack=2, locals=2, args_size=1 0: bipush 100 2: istore_1 3: iload_1 4: iinc 1, 1 //Il secondo variabile locale viene incrementato di 1 7: istore_1 //Salvato nel variabile locale 8: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream; 11: iload_1 //Il parametro caricato è il secondo nella pila, quindi è ancora 100 12: invokevirtual #22 // Method java/io/PrintStream.println:(I)V 15: return
Per l'esempio numero due, in realtà non è difficile, il risultato è 101, attenzione a guardare il flusso, non puoi più commettere errori simili in futuro. (Il flusso è: prima si confronta temp=i, temp>100, ovviamente non è vero, si aggiorna i+=1, si salta alla frase syso, il numero stampato sarà naturalmente 101, il ciclo di nuovo ha temp=i, temp>100, questa volta è vero, quindi i+=1, si esce direttamente dal ciclo, non si esegue la frase all'interno del while).
L'assemblaggio dell'esempio numero due (selezionato solo il metodo main):
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Codice: stack=2, locals=2, args_size=1 0: bipush 100 //100 in pila 2: istore_1 //salvare nel secondo var locale (il primo var locale è il parametro del metodo) 3: iload_1 //caricare dal secondo var locale 4: iinc 1, 1 //aumentare il valore int nella posizione locale 2 di 1 (variabile locale auto-incremento, il risultato rimane nella variabile locale, la sommità della pila operandi 1 non cambia) 7: bipush 100 //100 in pila 9: if_icmple 15 //comparare i due valori int di sommità della pila operandi, se il primo è minore o uguale al secondo, poi saltare a 15 riga 12: goto 25 //saltare a 25 riga (cioè la sommità della pila operandi 1>la sommità della pila operandi 2) 15: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 18: iload_1 // //caricare dal primo var locale 19: invokevirtual #3 // Method java/io/PrintStream.println:(I)V //chiamare questo metodo 22: goto 3 //saltare nuovamente a 3, ancora un ciclo 25: return //uscita
Il terzo esempio:
package test; public class Plus_Test03 { static int proPlus() { int i = 55; int j = ++i; return j; //56 } static int postPlus() { int i = 55; int j = i++; return j; //55 } public static void main(String[] args) { System.out.println(proPlus());//56 System.out.println(postPlus());//55 } }
Il terzo esempio di assemblaggio:
static int proPlus(); descriptor: ()I flags: ACC_STATIC Codice: stack=1, locals=2, args_size=0 0: bipush 55 //55 spinto nello stack 2: istore_0 //memorizza l'elemento in cima allo stack come primo local var 3: iinc 0, 1 //il primo local var + 1 6: iload_0 //caricato dal local var 7: istore_1 //salvato nel secondo local var 8: iload_1 //punta allo stack del secondo local var 9: ireturn static int postPlus(); descriptor: ()I flags: ACC_STATIC Codice: stack=1, locals=2, args_size=0 0: bipush 55 2: istore_0 3: iload_0 //caricato nello stack 4: iinc 0, 1 //il primo local var + 1 7: istore_1 8: iload_1 9: ireturn
Evidentemente, la differenza tra il ++ pre e il ++ post è nel segmento blu (//il primo local var + 1) qui sopra, che sono invertiti. Per il ++ pre, il numero nel local var viene aumentato e caricato nello stack, mentre per il ++ post viene caricato prima dal local var nello stack e poi il local var viene aumentato, come se avesse lasciato una copia di backup.
Conclusione:
Primo. Entrambi i ++ pre e ++ post aumentano prima il valore della variabile, non il ++ pre che aumenta prima e poi l'operazione, né il ++ post che opera prima e poi aumenta.
Secondo. Dal punto di vista del programma, il ++ post prima assegna il valore della variabile a una variabile temporanea, poi aumenta il valore della variabile e successivamente utilizza quella variabile temporanea per l'operazione.
Terzo. Dal punto di vista dell'instruzione, il ++ post prima di eseguire l'instruzione di aumento (iinc) premette di spingere il valore della variabile nello stack, esegue l'instruzione di aumento e utilizza il valore prima spinto nello stack.
Spero che con questo articolo tu possa comprendere completamente la differenza tra i ++ pre e i ++ post, grazie per il supporto al nostro sito!