Sunday, September 17, 2006

Java Tutorials: i = i++

This one of the frequently asked questions in interview. This question is frequently asked in 'C', but sometimes in 'Java' also.

What is the output of the program?


int i = 0;
i = i++;
System.out.println(i);


In C language, Dennis Ritchie has mentioned in the book "The C Programming Language", the behaviour is undefined and left to implementations. But most of the implementations produce the result as '0'.

Let us see, what will be the output in 'Java'?
When the questions is asked to many people, they immediately said the answer as '1'. They gave the following explanation.

This is wrong.
The line

i=i++;

is equivalent to

i=i;
i++;


That is, the value of i(0) is stored in the LHS, i.e. 'i'. Then the value of 'i' is incremented to '1' and then stored in 'i' and hence the result '1'.

Unfortunately, the answer is wrong. Let us see the reason.

i++ means post increment. It means, the value will be incremented after the operation is performed on it. It doesnt mean, the statement will be completed before execution. That is the value of the variable 'i' will be stored in a temporary location, then the value is incremented and then, the actual operation is performed, in this case assignment, on the value in the temporary location.

Hence,

i = i++;

is equivalent to,

int temp = i; // temp = 0
i++; // i=1
i = temp; // i = 0


Hence we get the result as '0'.

To get a clear understanding, let us look at the byte code for this operation.


public class Increment {

public static void main(String[] args) {
int i=0;
i=i++;
// System.out.println(i); // commented out to avoid unnecessary lines
}

}


Compile the file 'Increment.java'.

Java Byte Code:

In the command line, type,
> javap -c Increment

This will display the methods and the byte code for the Increment class. The byte code will be displayed in the form of mnemonics - human readable form.

The following lines will be printed:

C:\Projects\test\src>javap -c Increment
Compiled from "Increment.java"
public class Increment extends java.lang.Object{
public Increment();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return

public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
7: return
}


Let us concentrate on the byte code for the main method. Before getting in to this problem, you should have a good understanding about the Java Virtual Machine architecture.
Let us just have a brief introduction about Java Virtual Machine.

Java Virtual Machine
The JVM is Stack Based. That is, for each operation, the data will be pushed into the stack and from the stack the data will popped out to perform the operation. There is another data structure, typically an array to store the local variables.
The local variables are given ids which are just the index to the array. For a non-static method, 'this' reference will be at the array index '0', followed by method parameters and then the other local variables. For static methods, the parameters will start with '0' followed by local variables.

Program Illustration

Let us look at the mnemonics in main() method line by line.

Stack and Local Variables Array before the start of main() method.


| | args i
|---| --------------
| | | | |
|---| --------------
|___|
Stack Local Variable


0: iconst_0
The constant value '0' is pushed to the stack.


| | args i
|-----| --------------
| | | | |
|-----| --------------
| 0 |
-----
Stack Local Variable


1: istore_1
The top element of the stack is popped out and stored in the local variable with index '1'. That is 'i'.


| | args i
|-----| --------------
| | | | 0 |
|-----| --------------
| |
-----
Stack Local Variable


2: iload_1
The value at the location 1, is pushed into the stack.



| | args i
|-----| --------------
| | | | 0 |
|-----| --------------
| 0 |
-----
Stack Local Variable

3: iinc 1, 1
The value at the memory location '1' is incremented by '1'.


| | args i
|-----| --------------
| | | | 1 |
|-----| --------------
| 0 |
-----
Stack Local Variable

6: istore_1
The value at the top of the stack is stored to the memory location '1'. That is '0' is assigned to 'i'.


| | args i
|-----| --------------
| | | | 0 |
|-----| --------------
| |
-----
Stack Local Variable


Hence, we get the result as '0', and not '1'.

Unlike C/C++, this behaviour is guaranteed in Java.

I think this article will give a good insight about the Java Language and the Java VM.

11 Comments:

Blogger Janani said...

Wow... Amazing details. Thnks a lot for these info.

7:52 PM  
Blogger Unknown said...

That is some extensive research! excellent!

10:57 AM  
Blogger Jayaprabhakar said...

Thanks Janani... Thanks Thyaga...

Happy to see new faces in my blog...

11:01 AM  
Anonymous Anonymous said...

The explanation is good and detail.

9:34 PM  
Blogger Jayaprabhakar said...

Thanks for visiting my blog Krishnamoorthy.

9:53 PM  
Blogger Krishnakanth Soni said...

Great Explanation !! Thanks

7:58 AM  
Blogger Manki said...

Interesting to know; but seriously I will think twice before joining a company if I were asked this question in the interviews. I am darn sure no sensible programmers write such code in production software. (Also I think that we don't need to know these details unless our job is to write compilers.)

8:46 AM  
Blogger Sandeep said...

this is a very good snippet of code giving an insight into the internals and removing confusions.

11:53 PM  
Blogger Unknown said...

you have a nice site.thanks for sharing this site. various kinds of ebooks are available here

http://feboook.blogspot.com

8:30 PM  
Anonymous Anonymous said...

Thanks a lot ....hats off to you..

4:20 AM  
Blogger Kevat patel said...

Nice article to understand this concept in depth.
The explanation given at the end of this article with the byte code is excellent to understand.
Thanks for posting this article, it is really marvelous to understand this concept guys.

12:38 AM  

Post a Comment

<< Home