English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Analisi dettagliata e codice di esempio per operatori pre e post ++

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!

Ti potrebbe interessare