java‎ > ‎

Understanding that parameters are passed by value and not by reference

posted Jun 20, 2010, 8:00 PM by Kuwon Kang

Level: Introductory

Peter Haggar (haggar@us.ibm.com), Senior Software Engineer, IBM

01 Sep 1999

Editor's note: The following articles are excerpts from the book "Practical Java" published by Addison-Wesley. You can order this book at Borders.com.

A common misconception exists that parameters in Java are passed by reference. They are not. Parameters are passed by value. The misconception arises from the fact that all object variables are object references. This leads to some unexpected results if you do not understand exactly what is happening. For example:

   import java.awt.Point;    class PassByValue    {      public static void modifyPoint(Point pt, int j)      {         pt.setLocation(5,5);                                      //1         j = 15;         System.out.println("During modifyPoint " + "pt = " + pt +                            " and j = " + j);      }      public static void main(String args[])      {         Point p = new Point(0,0);                                 //2         int i = 10;         System.out.println("Before modifyPoint " + "p = " + p +                            " and i = " + i);         modifyPoint(p, i);                                        //3         System.out.println("After modifyPoint " + "p = " + p +                            " and i = " + i);       }    }

This code creates a Point object, initialized to (0,0) , and assigns it to the object reference variable p at //2. It then assigns the primitive int i the value 10 . The static modifyPoint method is then called at //3, passing p and i. The modifyPoint method calls the setLocation method on the first parameter, pt , changing its location to (5,5) . In addition, the second parameter, j , is assigned the value 15. When the modifyPoint method returns, method main prints the values for p and i . What is the output of this code and why?

The output of this code is as follows:

   Before modifyPoint p = java.awt.Point[x=0,y=0] and i = 10    During modifyPoint pt = java.awt.Point[x=5,y=5] and j = 15    After modifyPoint p = java.awt.Point[x=5,y=5] and i = 10

This output shows that the modifyPoint method changed the Point object created at //2 but not the int,i . In main , is assigned the value 10. Parameters are passed by value, therefore, a copy of i is passed to the modifyPoint method. This method changes the value of the copy to 15 and returns. The original value, i in main , is not changed.

On the other hand, you might think the Point object created at //2 is unmodified by the modifyPoint method. After all, Java passes parameters by value. Therefore, when modifyPoint is called with the Point object created at //2, a copy is made for the modifyPoint method to work with. Changes to the Point object in modifyPoint are not reflected in main because there are two different objects. Right? Wrong.

Actually, the modifyPoint method is working with a copy of a reference to the Point object, not a copy of the Point object. Remember that p is an object reference and that Java passes parameters by value. More specifically, Java passes object references by value. When p is passed from main to the modifyPoint method, a copy of the value of p, the reference, is passed. Therefore the modifyPoint method is working with the same object but through the alias, pt . After entering the modifyPoint method, but before the execution of the code at //1, the object looks like this:

Figure 1Figure 1 

Therefore, after the code at //1 is executed, the Point object has changed to (5,5) . What if you want to disallow changes to the Point object in methods such as modifyPoint ? There are two solutions for this:

  • Pass a clone of the Point object to the modifyPoint method.
  • Make the Point object immutable.

 

About the author

 
Comments