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;
}
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 incrementednums
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 exceptionThe 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.
See more on this question at Stackoverflow