Argument passing in Java is simple but sometimes confusing. Let’s go over some concepts briefly before diving into it.
If you come from a C/C++ programming background, you’ve probably heard of the “Call By Value” and “Call By Reference” argument passing concepts.
Briefly,
- Call by Value : A copy of the object instance is passed to called method. Any modifications made on the object inside the method will not be reflected back to the original object.
- Call by Reference : A reference to the original object is passed to called function. This reference may be thought as an alias for the original object and any modification done on the alias object inside the method actually done on the original object.
In this sense what about JAVA?
In Java, parameters are passed to the methods by object value. Another words it is “call by value” but there is a trick when passing complex object types.
First of all, let’s start with simple object types and try to change their values in a method.
public static void main(String[] args){
String someString = "someString";
Integer someInteger = 25;
char someChar = 'a';
int someInt = 5;
System.out.println("Before method call : " + someString + " " + someInteger + " " + someChar + " " + someInt);
changeValues(someString, someInteger, someChar, someInt);
System.out.println("After method call : " + someString +" "+someInteger+" "+someChar+" "+someInt);
}
private static void changeValues(String anyString, Integer anyInteger, char anyChar, int anyInt) {
anyString = "anotherString";
anyInteger = 55;
anyChar = 'b';
anyInt = 6;
}
And the result is :
Before method call : someString 25 a 5
After method call : someString 25 a 5
In Java, we already know that wrapper objects like strings and integers are immutable. Also, as shown, the values of the primitive types remains same after the method call. This result is compliant with the call by value definition.
How about passing complex objects?
Let’s see how complex objects are passing.
Suppose, we have an object called Dog with a simple name property.
public class Dog {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "dog name = " + name;
}
}
First we initialize our dog object and give it a name “Max”. Then we pass this dog object to changeMyDogName method in order to change dog name.
public static void main(String[] args){
Dog myDog = new Dog();
myDog.setName("Max");
System.out.println("Before method call : " + myDog.toString());
changeMyDogName(myDog);
System.out.println("After method call : " + myDog.toString());
}
private static void changeMyDogName(Dog dog) {
dog.setName("Toby");
dog = new Dog();
dog.setName("Jake");
}
And the result is :
Before method call : dog name = Max
After method call : dog name = Toby
Confused?
As you can see, the dog name is changed to “Toby” after the method call. You might think if all object values are copied, the dog name should not be changed and should remain as “Max”. The trick is that what gets copied to the method is the object reference, not the object values.
You might also wonder, why the dog name was not changed to “Jake” if object reference is copied to the method. We created a new dog object and named it “Jake”, right? In order to answer this question let me visualize it.
First we created a dog with a name “Max”. Lets say it has a red lead like the following picture. When we call changeMyDogName we are actually passing this red lead.
As soon changeMyDogName method is initialized. The red lead is copied. Let’s say it is copied as a blue lead as the following picture.
At that point, both blue and red leads are fastened to original dog. So any changes made to this dog are actually made to the original dog. This is why the dog name was changed to “Toby”.
On the other hand, when we create a new dog in the method, we are actually creating a new dog.
At that point, blue lead is now fastened to a completely different dog(Jake) so whatever done to new dog does not affect the original dog.
As a result, although many considered Java as call by reference it is actually call by value. As described above, while passing complex objects, the passed value is a copy of the object reference.
disclaimer : The lovely dog picture is taken from www.groomers-online.com