В Java, как оператор post increment действует в операторе return?

Учитывая следующий код, ixAdd сделает то, что вы ожидаете, i. е. вернуть значение ix до инкремента, но увеличивать член класса до выхода из функции?

class myCounter {
    private int _ix = 1;

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

Я не был уверен, что обычные правила для post/pre increment также будут применяться в операторах return, когда программа покидает фрейм стека (или что бы то ни было в Java) этой функции.

Ответ 1

Ключевой частью является то, что приращение/декремент сообщения происходит сразу после вычисления выражения. Это происходит не только до того, как произойдет возврат - это происходит до того, как будут оценены последующие выражения. Например, предположим, что вы написали:

class myCounter {
    private int _ix = 1;

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

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

Это также выдаст результат с добавлением, потому что приращение происходит до вызова giveMeZero().

Ответ 2

Хорошо, посмотрим на байт-код (используйте javap -c <classname>, чтобы увидеть его сами):

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

}

Как вы можете видеть, инструкции 6 и 7 в ixAdd() обрабатывают приращение перед возвратом. Поэтому, как и следовало ожидать, оператор декремента действительно имеет эффект при использовании в операторе return. Обратите внимание, что перед тем, как эти два появятся, есть инструкция dup; инкрементное значение (конечно) не отражается в возвращаемом значении.

Ответ 3

Да, обычные правила применяются для приращения post даже в операторе return. В принципе, то, что он будет делать на низком уровне, сохраняет возвращаемое значение в регистр, затем увеличивает член класса, а затем возвращает метод.

Вы можете увидеть это в более позднем ответе на этот вопрос, который показал код байта.

Ответ 4

Да, это так.

Но не делайте этого, это плохой стиль, чтобы иметь побочные эффекты в выражениях.

Ответ 5

Он возвращает значение перед приращением, а затем увеличивает _ix. Поэтому при первом вызове метода ixAdd в экземпляре myCounter он вернет 1, второй раз он вернет 2 и т.д.