Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assignment gives unexpected answer

Tags:

java

Today I've encountered the following problem, to which I can't seem to find a solution:

int i, j, k;

i = j = k = 3;

i = k++;

So it seemed logical to me that the variable 'i' must have the value 4 now, since we assigned the increment of 'k' to it. In the multiple choice test, the correct values after the third line were instead:

k = 4

and

i != 4

Since we assigned the increment of k to i, how come the given solution is the exact opposite to what I had expected? Thanks in advance!

like image 914
Johanna N.-A. Avatar asked Feb 02 '14 12:02

Johanna N.-A.


1 Answers

Firstly, as noted by JB Nizet, don't do this. Very occasionally I'll use a postfix increment within another expression, for thing likes array[index++] = value; but very often I'll pull it out into two statements for clarity.


I wasn't going to answer this question, but all the answers (at the time of posting) make the same mistake: this isn't a matter of timing at all; it's a matter of the value of the expression k++.

The assignment to i happens after the increment of k - but the value of the expression k++ is the original value of k, not the incremented value.

So this code:

i = k++;

Is equivalent to:

int tmp = k;
k++;
i = tmp;

From section 15.14.2 of the JLS (emphasis mine):

[...] Otherwise, the value 1 is added to the value of the variable and the sum is stored back into the variable. Before the addition, binary numeric promotion (§5.6.2) is performed on the value 1 and the value of the variable. If necessary, the sum is narrowed by a narrowing primitive conversion (§5.1.3) and/or subjected to boxing conversion (§5.1.7) to the type of the variable before it is stored. The value of the postfix increment expression is the value of the variable before the new value is stored.

This difference is very important, and can easily be seen if instead of using the postfix expression for an assignment, you call a method:

public class Test {

    private static int k = 0;

    public static void main(String[] args) throws Exception {
        foo(k++);
    }

    private static void foo(int x) {
        System.out.println("Value of parameter: " + x);
        System.out.println("Value of k: " + k);
    }
}

The result is:

Value of parameter: 0
Value of k: 1

As you can see, k has already been incremented by the time we call the method, but the value passed into the method is still the original value.

like image 147
Jon Skeet Avatar answered Oct 30 '22 05:10

Jon Skeet