Tuesday, 7 December 2010

Java By Value or By Reference?

HTML Source EditorWord wrap HTML Source EditorWord wrap

I have recently seen several long threads discussing the topic "Does Java pass parameters by value or by reference?".  I wanted to add my two cents here.

The short answer is as follows:

1) Java passes primitive parameters by value

2) Java passes object references by value

The sticking point is that #2 is considered by many to be the definition of passing by reference.

The long answer:

First, let me say that definition of terms is critical in this discussion.  It is easy to disagree on larger points when we don't agree on the definition of key terms.

For the purposes of this discussion I define pass by value to be creating a copy of the value to be passed and passing the copy to the formal parameter of the method.

Similarly, pass by reference is defined as passing a reference (typically called a pointer) to the value to be passed.

One other important point is that in Java we do not pass objects as parameters, we pass references.  I believe that this is the key piece of information that gets missed during discussions about this topic.

In Java, parameters only come in two flavors: primitives and references.  Java always makes a copy of the parameter and passes the copy, hence Java ALWAYS passes by value.

You can see that this is true in the code example below:

package byvalue;
import java.awt.Point;
public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        main.test();
    }
    void test() {
        int i = 1;
        Point point1 = new Point(1,1);
        Point point2 = new Point(2,2);
        
        testRef(i, point1, point2);
        System.out.println("i=" + i + 
                " point1=" + point1.getX() +"," + point1.getY() + 
                " point2=" + point2.getX() +"," + point2.getY());
    }
    void testRef(int i, Point p1, Point p2) {
        i = 2;
        p1 = new Point(3,3);
        p2.setLocation(4,4);
    }
}

Output:  i=1 point1=1.0,1.0 point2=4.0,4.0

The change to the value of i and assigning a new object to p1 had no effect outside the testRef method.

However, and this is the point that the pass by reference folks hang their hat on, the location of point2 does get modified!  This is, of course, because the value passed to the method is a reference.  While the reference cannot be made to point to a different object, the object it references can be manipulated.

From a practical point of view for most engineers, what we call it matters less than understanding how it works.  What you need to know is that primitives are passed by value and references are passed by value, so changes to those parameters inside the called method have no impact outside the method.  However, the object pointed to by a passed reference is in fact the same object outside the method and any changes made to the object inside the method will be seen outside the method.

Let me know what you think.

 

Technorati Tags:

Posted by john at 7:40 PM in Java
« August »
SunMonTueWedThuFriSat
    123
45678910
11121314151617
18192021222324
25262728293031