1

I'm familiar with Call by reference concept in java but after seeing this code I'm confused

public class App 
{
    public static void main( String[] args )
    {
        Test t1 = new Test(1);
        Test t2 = new Test(8);
        App.doSomething(t1, t2);
        System.out.print(t1.a);
        System.out.print(t2.a);
    }
    public static void doSomething(Test t1, Test t2){
        System.out.print(t1.a++);
        System.out.print(t2.a++);
        t1 = new Test(999);
        t2 = new Test(888);
    }
}

Prints:

1
8
2
9

Why does'nt value of "t1.a" and "t1.b" in the main function change to 888 and 999?

mhsaeedi
  • 27
  • 6
  • 3
    This is pretty much the exact scenario covered in [Is Java "pass-by-reference"?](http://stackoverflow.com/questions/40480/is-java-pass-by-reference) The `++` mutates the object's internal state, the `=` reassigns the reference locally. – Radiodef Mar 05 '14 at 14:18

5 Answers5

5

Java does not have call by reference. All parameters are passed by value -- but in the case of a parameter that is an object, the "value" that is passed is a reference to the object.

As a result, if you use the local reference to that object within the method to modify the object, it will modify the same object. However, if you assign something to that local variable, then it no longer has a reference to the original object, and subsequent changes will not affect the original object.

Jacob Mattison
  • 50,258
  • 9
  • 107
  • 126
0

Thats why you typically set your method arguments to final - to avoid this kind of confusion :) findbugs would actually produce a style warning about this effect

light_303
  • 2,101
  • 2
  • 18
  • 35
0

That's because in java arguments are always pass-by-value.

In your example you pass a reference to a object, however this reference is passed by value. In other words, new local variable t1 is created and initialized with the references to your object that has been passed in the argument. So when you assign new Test() to it, only the local variable references the new object.

Kuba Spatny
  • 26,618
  • 9
  • 40
  • 63
0

In Java everything is pass by value. The scopes of the 2 t1's and t2's are different. One is in the scope of main() and the other is in the scope of doSomething(). So the reason it isn't changed to 888 or 999 is because those values don't exist once you leave doSomething().

9er
  • 1,604
  • 3
  • 20
  • 37
0

Novices have a hard time with this, I'll try to explain in story form:

If I let you borrow my sticky note (with my name on the top) with an arrow that points to the red sofa, and you take my sticky note and erase my arrow and put on a new arrow to the green sofa. When you finish your shenanigans, I will have a sticky note with my name on it that points to the green sofa. My stickynote was changed.

If however, I let you borrow my sticky note with my name on it, which has an arrow that points to the red sofa, and you take my sticky note and set it to the side, and you make a new sticky note with your name on it, then you put an arrow on it pointing to the green sofa, and you finish your shenanigans, then my sticky note is unchanged with my name pointing to the red sofa. You created your sticky note that I can't reach.

When you crammed a new object into t1, you didn't destroy the old one because you do not have authorization to do so. You simply pushed it to the side, and created a new one, which nobody has access to except you.

This line:

t1 = new Test(999);

Does not erase the old t1. You simply make a new t1 that is only local to the method, which is garbage collected after the method ends. With this line, you didn't change the parameter passed in, you created a new variable with the same name.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335