What are the semantics of java's postfix increment operator on the left side of an assignment statement and why do they differ from the right side?

I was working on a leetcode question [1] and noticed something that caught my eye.

When I write a line of code as:

nums[i] = nums[(i++)+count];

I pass all the tests and my answer is accepted. If however I change the same line to:

nums[i++] = nums[i+count];

I get an ArrayOutOfBounds exception. Why is this?

Here is the full code:

public void moveZeroes(int[] nums) {
    int count = 0, i = 0;
    while(i+count < nums.length){
        if(nums[i+count] == 0)
            count++;
        else
            nums[i] = nums[(i++)+count];
    }
    for(;i<nums.length; i++)
        nums[i] = 0;
}

[1] https://leetcode.com/problems/move-zeroes/

Jon Skeet
people
quotationmark

The answer lies in JLS 15.26.1. Basically, this is the order of things in the case of

nums[i++] = nums[i+count];
  • nums is evaluated (as part of the left-hand side)
  • i++ is evaluated to find the index; the result is the original value of i, but i is then incremented
  • At this point, we've evaluated which array element we're assigning to
  • nums is evaluated (as part of the right-hand side)
  • i+count is evaluated; note that this uses the already incremented value of i, which is why you're getting an exception
  • We now know which array element we're fetching
  • Fetch the value of that element
  • Assign the value into the LHS element we identified earlier

The important part is that the left operand of the assignment operator is evaluated before the expression on the right operand. So the side-effect while evaluating the array index expression in the left operand affects the evaluation of the right operand.

people

See more on this question at Stackoverflow