2009-03-17 2 views
14

Mit dem folgenden Code wird ixAdd tun, was Sie erwarten würden, ich. e. den Wert von ix vor dem Inkrement zurückgeben, aber den Klassenmember vor dem Verlassen der Funktion inkrementieren?Wie verhält sich ein Post-Inkrement-Operator in Java in einer return-Anweisung?

class myCounter { 
    private int _ix = 1; 

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

Ich war nicht ganz sicher, ob die üblichen Regeln für Post/pre Zuwachs auch im Gegenzug Aussagen gelten würde, wenn das Programm den Stapelrahmen verlässt (oder was auch immer es ist in Java) der Funktion.

+1

Warum versuchst du es nicht? –

+2

ehm .. meinst du, wie den Code oben in meinem Editor einfügen und ausführen? Ich weiß es nicht, Entschuldigung. :-p Ich werde mir eine Tasse Kaffee holen ... –

+0

für nahe gewählt ... Ich dachte, der Autor könnte es sofort schließen? –

Antwort

25

Der Schlüssel Teil ist, dass ein Post-Inkrement/Dekrement passiert sofort, nachdem der Ausdruck ausgewertet wird. Dies geschieht nicht nur vor der Rückkehr - es passiert, bevor spätere Ausdrücke ausgewertet werden. Zum Beispiel: Angenommen, Sie schrieb:

class myCounter { 
    private int _ix = 1; 

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

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

, die auch aus dem erhöhten Ergebnis drucken würde, weil der Zuwachs geschieht vor giveMeZero() aufgerufen wird.

+0

Danke für die Antwort, Jon. Wie Paul Tomblin ausführte, hätte auch die Eingabe des Codes in meinem Editor anstelle des Posts darauf geantwortet. Aber jetzt habe ich mehr davon, als ich verlangt habe. –

+0

@Jon: Für Leute, die von C nach Java kommen (was eine Menge Leute sein werden), ist das eine gute Sache, darauf hinzuweisen. Als langjähriger Java-Benutzer, der C lange, lange Zeit benutzt hatte, wusste ich nicht, dass Java definierte, wie ++ so viel klarer funktioniert als C. Ich habe gelernt, "schlaue" ++ Verwendung von C zu vermeiden! – Eddie

+0

_Nicht nur passiert es, bevor die Rückgabe auftritt_, sondern return-Anweisung gibt den inkrementierten Wert nicht zurück, wenn es eine lokale Variable ist. Ihr Beispiel zeigt eine globale Variable. – ernesto

1

Ja, die üblichen Regeln gelten für Post-Inkrement sogar bei einer Rückgabeanweisung. Im Grunde wird das, was es auf einer niedrigen Ebene tun wird, den Rückgabewert in ein Register speichern, dann das Klassenmitglied inkrementieren und dann von der Methode zurückkehren.

Sie können dies in a later answer zu dieser Frage sehen, die den Byte-Code zeigte.

0

Ja, tut es.

Aber tun Sie das nicht, es ist ein schlechter Stil, Nebenwirkungen in Ausdrücken zu haben.

+0

Die Nebenwirkung hier ist sehr beabsichtigt und ich kann nicht sehen, dass es schadet. –

+0

Aber es macht es schwer zu verstehen, wie Ihre Frage zeigt. – starblue

16

Nun, schauen wir uns die Bytecode aussehen (javap -c <classname> verwenden, es selbst zu sehen):

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 

} 

Wie Sie sehen können, Anweisungen 6 und 7 in ixAdd() den Zuwachs vor der Rückkehr behandeln. Wie zu erwarten, hat der Dekrementoperator tatsächlich eine Wirkung, wenn er in einer Return-Anweisung verwendet wird. Beachten Sie jedoch, dass es eine dup Anweisung gibt, bevor diese beiden erscheinen; der inkrementierte Wert wird (natürlich) nicht im Rückgabewert wiedergegeben.

0

Es gibt den Wert vor dem Inkrement zurück und erhöht dann _ix. Wenn Sie also zum ersten Mal die Methode ixAdd für eine Instanz von myCounter aufrufen, wird 1 zurückgegeben, beim zweiten Mal wird 2 zurückgegeben und so weiter.

Verwandte Themen