2009-03-17 2 views
14

Dato il seguente codice, ixAdd farà quello che ti aspetteresti, io. e. restituire il valore di ix prima dell'incremento, ma incrementare il membro della classe prima di lasciare la funzione?In Java, come agisce un operatore di post-incremento in una dichiarazione di reso?

class myCounter { 
    private int _ix = 1; 

    public int ixAdd() 
    { 
     return _ix++; 
    } 
} 

non ero del tutto sicuro se si applicano anche le regole usuali per la post/pre incremento nelle istruzioni di ritorno, quando il programma lascia lo stack frame (o qualunque cosa sia in Java) della funzione.

+1

Perché non ci provi? –

+2

ehm .. intendi, come incollare il codice sopra nel mio editor ed eseguirlo? Non lo so, mi dispiace. :-p Vado a prendermi una tazza di caffè ... –

+0

votato per chiudere ... pensavo che l'autore potesse chiuderlo immediatamente? –

risposta

25

La parte fondamentale è che un incremento/decremento di post avviene immediatamente dopo la valutazione dell'espressione. Non solo si verifica prima che si verifichi il ritorno, ma prima che vengano valutate le espressioni successive. Per esempio, supponiamo che hai scritto:

class myCounter { 
    private int _ix = 1; 

    public int ixAdd() 
    { 
     return _ix++ + giveMeZero(); 
    } 

    public int giveMeZero() 
    { 
     System.out.println(_ix); 
     return 0; 
    } 
} 

Che sarebbe stampare il risultato incrementato pure, perché l'incremento avviene prima giveMeZero() si chiama.

+0

Grazie per la risposta, Jon. Come ha sottolineato Paul Tomblin, anche la digitazione del codice nel mio editor al posto del post avrebbe risposto. Ma ora ne ho ricavato di più di quello che ho chiesto. –

+0

@Jon: per le persone che arrivano da C a Java (che saranno molte persone), questa è una buona cosa da sottolineare. Da lungo tempo utente Java che per la prima volta usava C per molto, molto tempo, non sapevo che Java definisse come ++ funziona in modo molto più chiaro di C. Ho imparato ad evitare l'uso "intelligente" ++ di C! – Eddie

+0

_Non avviene solo prima che si verifichi il ritorno_ ma l'istruzione di reso non restituisce il valore incrementato se è una variabile locale. Il tuo esempio mostra una variabile globale. – ernesto

1

Sì, le normali regole si applicano per il post incremento anche su un estratto conto. Fondamentalmente, ciò che farà a un livello basso è memorizzare il valore di ritorno in un registro, quindi incrementare il membro della classe, quindi tornare dal metodo.

È possibile vedere questo in a later answer a questa domanda che mostrava il codice byte.

0

Sì, lo fa.

Ma non farlo, è uno stile sbagliato avere effetti collaterali nelle espressioni.

+0

L'effetto collaterale qui è molto inteso e non riesco a vederlo fare alcun danno. –

+0

Ma è difficile da capire, come mostra la tua domanda. – starblue

16

Bene, diamo un'occhiata al bytecode (utilizzare javap -c <classname> per vedere voi stessi):

Compiled from "PostIncTest.java" 
class myCounter extends java.lang.Object{ 
myCounter(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: aload_0 
    5: iconst_1 
    6: putfield #2; //Field _ix:I 
    9: return 

public int ixAdd(); 
    Code: 
    0: aload_0 
    1: dup 
    2: getfield #2; //Field _ix:I 
    5: dup_x1 
    6: iconst_1 
    7: iadd 
    8: putfield #2; //Field _ix:I 
    11: ireturn 

} 

Come si può vedere, le istruzioni 6 e 7 ixAdd() gestire l'incremento prima del ritorno. Pertanto, come ci aspetteremmo, l'operatore di decremento ha effettivamente un effetto quando viene utilizzato in una dichiarazione di reso. Si noti, tuttavia, che esiste un'istruzione dup prima che questi due vengano visualizzati; il valore incrementato è (ovviamente) non riflesso nel valore di ritorno.

0

Restituisce il valore prima dell'incremento, quindi incrementa _ix. Pertanto, la prima volta che si chiama il metodo ixAdd su un'istanza di myCounter, verrà restituito 1, la seconda volta restituirà 2 e così via.