2009-03-17 6 views
14

Étant donné le code suivant, ixAdd fera-t-il ce que vous attendez, i. e. renvoie la valeur de ix avant l'incrément, mais incrémente le membre de la classe avant de quitter la fonction?En Java, comment un opérateur post-incrément agit-il dans une déclaration de retour?

class myCounter { 
    private int _ix = 1; 

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

Je n'étais pas sûr si les règles habituelles pour incrément post/pre s'appliqueraient également dans les déclarations de retour, lorsque le programme quitte le cadre de pile (ou quoi que ce soit en Java) de la fonction.

+1

Pourquoi ne l'essayez-vous pas? –

+2

ehm .. vous voulez dire, comme coller le code ci-dessus dans mon éditeur et l'exécuter? Je ne sais pas, désolé. :-p Je vais aller me chercher une tasse de café ... –

+0

a voté pour fermer ... Je pensais que l'auteur pourrait juste le fermer immédiatement? –

Répondre

25

La partie clé est qu'un post-incrément/décrément se produit immédiatement après l'évaluation de l'expression. Non seulement cela se produit avant que le retour se produise - il arrive avant que toutes les expressions ultérieures soient évaluées. Par exemple, supposons que vous avez écrit:

class myCounter { 
    private int _ix = 1; 

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

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

Ce imprimerait ainsi le résultat incrémentée, parce que l'incrément se produit avant giveMeZero() est appelé.

+0

Merci pour la réponse, Jon. Comme Paul Tomblin l'a fait remarquer, le fait de taper le code dans mon éditeur à la place du message aurait également répondu. Mais maintenant j'en ai tiré plus que ce que je demandais. –

+0

@Jon: Pour les personnes venant de C à Java (ce qui sera beaucoup de monde), c'est une bonne chose à signaler. En tant qu'utilisateur Java de longue date qui a longtemps utilisé C pendant longtemps, je ne savais pas que Java définissait comment ++ fonctionne beaucoup plus clairement que C. J'ai appris à éviter l'utilisation "intelligente" ++ de C! – Eddie

+0

_Non seulement cela arrive avant que le retour ne se produise_ mais l'instruction return ne retourne pas la valeur incrémentée si c'est une variable locale. Votre exemple montre une variable globale. – ernesto

1

Oui, les règles habituelles s'appliquent à la post-incrémentation même sur une instruction return. Fondamentalement, ce qu'il fera à un niveau bas est de stocker la valeur de retour dans un registre, puis d'incrémenter le membre de la classe, puis de revenir de la méthode.

Vous pouvez voir ceci dans a later answer à cette question qui a montré le code de byte.

0

Oui, c'est le cas.

Mais ne faites pas cela, c'est mauvais style d'avoir des effets secondaires dans les expressions.

+0

L'effet secondaire ici est très prévu et je ne peux pas le voir faire de mal. –

+0

Mais cela rend difficile à comprendre, comme le montre votre question. – starblue

16

Eh bien, regardons le bytecode (utilisez javap -c <classname> pour voir vous-même):

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 

} 

Comme vous pouvez le voir, les instructions 6 et 7 dans ixAdd() poignée l'incrément avant le retour. Par conséquent, comme on peut s'y attendre, l'opérateur de décrémentation a en effet un effet lorsqu'il est utilisé dans une instruction return. Notez, cependant, qu'il existe une instruction dup avant que ces deux apparaissent; la valeur incrémentée n'est (bien sûr) pas reflétée dans la valeur de retour.

0

Il renvoie la valeur avant l'incrément, puis incrémente _ix. Par conséquent, la première fois que vous appelez la méthode ixAdd sur une instance de myCounter, elle renvoie 1, la seconde renvoie 2, et ainsi de suite.