Friday, August 5, 2011

Java: Pass by Value

I was in an interview and interviewer asked me the following question.

public static void main(){
          String s1 = "A";
          s1 = s1 + 1;
          System.out.println("Before function call S1 is:" + s1);
          modifyString(s1);
          System.out.println("After function call S1 is:" + s1);
}

String modifyString(String a){
          a = a + 2;
          return a;
}

What is the output of the following problem?

Though I knew Java is pass by value but at the time of function call Java passes memory reference of the objects. So with the conviction I wrote the output of the program.

Before function call S1 is: A1
After function call S1 is: A12

Interview was over, I returned home, wrote the program and ran it in my eclipse. Bomb... It exploded. Results were not as I expected. WTF, why are those results not the same as I expected? I am the Java bond I can not be wrong. Instantaneously I pinged for an assistance. I wanted to hear "there is a problem with my eclipse instance. I should dump the current eclipse and take the latest eclipse soon." But instead hearing those words  I got following response.

Before function call S1 is: A1
After function call S1 is: A1

My expectation were shattered and I started arguing. Argument ended with my broken believe and I figured out "I have to cover a lot more about java fundamentals".

Anyways let me tell  you how does java pass the object to the function. In general java do not differentiate between Objects and primitive data type. It uses copy operation to pass the value of both type of data types.
If you have overridden copy method of your class then java will copy the object based of your implementation otherwise it will copy the object shallowly, in other words we say java uses shallow copy functionality of the objects. In case of shallow copy it creates a new reference to the object passed to the method. Now whenever you change in this method, are reflected back in the mutable classes, whereas in case of immutable classes it is not possible to change the object so we refrain ourselves to changing anything in those classes.

Lets review the following program.


public class PassByValueInJava {

int xy = 0;
private static void modifyPav(PassByValueInJava pav3 ,PassByValueInJava pav4) {
int temp  = pav3.xy;
pav3.xy = pav4.xy;
pav4.xy = temp;
}

public static void main(String[] args) {
PassByValueInJava pav1 = new PassByValueInJava();
PassByValueInJava pav2 = new PassByValueInJava();
pav1.xy = 10;
pav2.xy = 20;
System.out.println("Before Modify:::: pav1 x:" + pav1.xy + "   pav2 x:" + pav2.xy);
modifyPav(pav1, pav2);
System.out.println("After Modify::::pav1 x:" + pav1.xy + "   pav2 x:" + pav2.xy);
}

}


Can you guess what is the output of the program written here?
After seeing the above example I thought it should not switch the values. So results should be the following
Before Modify:::: pav1 x:10 pav2 x:20
After Modify:::: pav1 x:20 pav2 x:10

Now it is strange. Why did swapping happened? Was there something different?

Okay, lets analyze what has happened in this program? Main function calls the modify function and providing them the copy of pav1 and pav2. As copy is a shallow copy, so in this case Java will create a reference which will point to the same memory location of the previous object. Memory location depicts the situation well here.

Why did not same thing happened when string object was passed to the method.
As string in java are immutable so java deals with string in a different manner. Initially when S1 = A then string was pointing to one memory location and as soon as S1 = S1 + 1, it creates new string object and S1 was assigned to it.

Now when Main called modify function s1 was pointing to A1 memory location whose reference was passed to modify function. When string s2 got changed, then it started pointing to the A12 string object's memory location. But s1 is still pointing to the A1 string object's memory location. That is why value for s1 did not modify.

So it is clear that java always uses pass by value and as java tackles string in a complete different way, this is the reason we see such a huge difference between objects and strings.

Program mentioned above could enhance with the following


public static void main(){
          String s1 = "A";
          s1 = s1 + 1;
          System.out.println("Before function call S1 is:" + s1);
          s1 = modifyString(s1);
          System.out.println("After function call S1 is:" + s1);
}

String modifyString(String a){
          a = a + 2;
          return a;
}

It will result in the expected output.