The question often arises, “Does Java pass-by-reference or does it pass-by-value?” meaning when an argument is passed to a method in Java, is it the memory address of the variable given to the method, or the value of the variable that is passed to the method. What happens when you change the values of the arguments passed to a method?
Without getting into discussions about the virtues of functional programming versus traditional object oriented programming, let’s answer the pass-by-reference or pass-by-value question.
Java uses pass-by-value. This gets a little confusing with objects, but we’ll stick to primitives for the moment. Java passes copies of variable values to methods. When passing primitives to methods, such as ints and bytes, any changes to the values of the method arguments are only of local scope to the method.
For example, in the following code, a primitive named
myInt is passed to the
changeTheInt() method. The method proceeds to attempt to change the value of argument
i. However, even though
i‘s value changes, this does not affect the value of
myInt. The changed value is kept in the scope of the local method because a copy of the original
myInt variable’s value was passed to the method, not the actual
Understanding pass-by-value in Java when it comes to primitives is easy. Understanding pass-by-value when it comes to objects in Java is a bit more challenging. Using a couple of examples will help.
First, let’s start with a simple object called
Clouds has the singular purpose of keeping track of how many clouds are in the sky. The constructor takes an
int for initializing the number of clouds in the sky.
Clouds also provides methods for changing the number of clouds in the sky, and printing the number of clouds in the sky.
So let’s get on with testing the behavior of Java when passing
Clouds objects to methods.
As I mentioned earlier, everything is passed-by-value in Java. So, when you construct an object and pass the object to a method, setting the method argument equal to a different object does not change the value of the original object that was passed to the method. Think about this and you will realize the behavior is exactly like that of primitives that are passed by value to methods.
The following test illustrates that behavior. A
Clouds object is passed to the
changingReference() method. The method argument of
clds is set equal to a new
Clouds object, but the original
clouds variable in the
main() method remains unaffected.
Now comes the tricky part. What are objects in Java? What actually gets passed-by-value to methods when an object is passed to a Java method?
When you look at the value of a primitive in Java’s memory, it is the value of the variable. However, when you look at the value of a Java object in Java’s memory it is the address to the real location of the object. In C terms, the value found in memory of a Java object is a pointer to the actual object’s location.
I know I just lost a whole bunch of you. Sorry. Let’s try that again.
Java stores the smallest descriptions of it’s variables possible as their actual value. This is for performance reasons. In the case of primitives, the smallest value possible is the actual value of the primitive. In the case of objects, the smallest value possible is the memory address of the actual object. That way, when copying an object to a method, the guts of the object (such as it’s attributes) don’t get copied. The address of the object gets copies.
That’s probably still confusing, but all you really need to remember is the result of this. An object that is passed to a method behaves like a pass-by-reference, because a copy of the object’s reference is passed to Java methods. Any calls to methods or changes of attributes of an object that is passed to a method results in changes to the attributes or calls to the original object.
For example, calling the
clds object’s setter in the following test results in a change to the
clouds object’s attribute.
Objects, like primitives, are passed-by-value in Java. However, the value copied and passed in the case of objects is the memory location, not the full object. For convenience, you can think of Java objects as passed-by-reference. Remember though, if you try setting objects equal to new objects inside methods, the change will be scoped only to the method. You cannot change the original object to a new object inside a method. You need to stick to calling its methods and changing its attributes to make changes to the original object.