One of the biggest confusion in Java programming language is that ?Is Java Pass by Value or Pass by Reference?? and most of the programmers are confused because they might not know the actual meaning of Pass by Value and Pass by Reference. So, Fix in your mind that:
?Java is strictly Pass by Value, there is no Pass by Reference?
I will explain how Java uses pass by value with examples and give you a proof that Java is only Pass by value. BUT one thing I will expect from you that you must have clear understanding about the Java memory allocation. If you are unfamiliar with the concept of memory allocation, you must gone through that before proceeding this tutorial. You can google it or here is my article on Stack vs Heap Memory in Java.
So, most importantly we have to be clear about the terminology ?pass by value? and ?pass by reference?. Some programmer says Java primitives are passed by value and objects are passed by reference, that?s not true.
Just have a look at image below before starting the actual context of this tutorial.
Pass by Value:
The actual arguments that are passed to a method, are evaluated and a value is derived (a copy is created) then this copied value is stored in a location (memory) and then this ?copied value? will become a formal argument to the invoked method. This is the mechanism Java uses.
Pass by Reference:
Formal arguments are just an alias to the actual arguments. It refers to the actual argument and any changes to the alias will reflect to the actual/original arguments and vice versa.
Java Language Specification says:
In Section 8.4.1 Formal Parameters
?When the method or constructor is invoked (15.12), the values of the actual argument expressions initialize newly created parameter variables, each of the declared type, before execution of the body of the method or constructor.?
It clearly says that the actual arguments are evaluated and values are given to the method as formal argument. So, when an object is passed to a method, that object?s reference is passed ?as value? (a copy) instead of object itself.
Java uses JVM Stack memory to create the new objects that are formal parameters. This newly created objects scope is within the boundary of the method execution. Once the method execution is complete, this memory can be reclaimed.
Let?s test this confusion by programming
We can run a simple swap test to check whether java is pass by value or pass by reference. We will create 2 objects in main() and pass them into a swap() method and then we will swap them inside the invoked method, after that we will check if the original objects changes or not.
Objects are NOT swapped because Java uses pass by value.
Does Java passes the Reference?
Everything is simple yet. Lets look at another example where we try to pass an object and modify that object in invoked method and then checks the original object whether changes reflected to it or not.
Object is modified now. If the actual argument is passed by value, how are we able to change an attribute of the original object? Confused now? This is because Java passes the object reference ?by value?. When an object is passed in argument, actually the reference (as a copy) instead of original object is being passed.
Let me explain this confusion. I will try to explain in two ways, A brief explanation and A detail explanation.
When an object is created Shape shape = new Shape(), a reference variable shape is created in stack and object new Shape() is created in heap. When an object reference is passed to a method, JVM actually creates a copy of that reference and passed as value to the method. So, in invoked method, any changes inside the object will reflect to the original argument BUT changing the references in invoked method doesn?t reflect in the original argument. See the image below.
In figure 1, there are two objects with variable name circle and square which references the location x100 and x102 having data ?Circle? and ?Square? respectively.
In figure 2, there are two objects named formal-circle and formal-square which references location x301 and x303 respectively. Here is the catch, content of the location x301 and x303 in heap are again references to another location x100 and x102. So, the called method has got the reference of the passed arguments. Using the reference it can manipulate only the content of the actual argument object, BUT it can not change the fact that circle points to x100 and square points to x102, that?s what we are trying to do when we swap the objects.
Important point to note is that ?the reference is copied as a value? to a new variable and it is given as formal parameter to the called method. It does not get circle variable which is the actual argument in scope. This is the key difference between pass by value and pass by reference.
? Inspired by the article written by Joe in javapapers.com
If you do not get the point that what is happening behind the scene, lets look at the detailed explanation.
Let me explain in detail what actually happens behind the scene. Consider Example 1 and look at the image below for before swapping was performed. (please ignore the execution process ofSystem.out.println())
As soon as a program starts executing, stack memory and heap memory will be created according to the JVM settings. Look at the Example 1, I am explaining Step by Step process with the help of image above.
Point 1: A shape object is created in heap with the memory address (x100) by containing data (?Circle?) and a reference variable circle (actual) is created in stack containing data (x100) is the reference to the object in heap.
Point 2: Same goes here, a shape object is created in heap with memory address (x102) by containing data (?Square?) and a reference variable square (actual) is created in stack containing data (x102) is the reference to the object in heap.
Point 3: An address for swap function calling is stored in PC Register as an instruction for the next execution.
Swap function is called now, before executing the inside of swap() function, formal arguments are created in stack with reference to the heap.
Point 4: A formal object is created in heap with memory address (x302) by containing data as another reference to the object in heap (x100) and a formal argument variable circle (formal) is created in stack containing data (x302) is the reference to the object in heap.
Point 5: Same goes here, a formal object is created in heap with memory address (x304) by containing data as another reference to the object in heap (x102) and a formal argument variable circle (formal) is created in stack containing data (x302) is the reference to the object in heap.
Lets the execution happened inside swap() now,
Point 1: An object is created in heap with memory address (x306) by containing data as another reference to the object in heap (x302) and a reference variable temp is created in stack containing data (x306) is the reference to the object in heap.
Point 2: Changing the reference of circle (formal) with square (formal). Now circle is referencing to x304 instead of x302 although the inside of x304 and x302 didn?t change that means changing the reference of formal variables doesn?t change inside of the object in heap.
Point 3: Same goes here, Changing the reference of square (formal) with temp. Now square is referencing to x302 instead of x304 although the inside of x302 and x304 didn?t change that means changing the reference of formal variables doesn?t change inside reference of heap.
One thing to notice here, the original references of circle and square are still pointing to x100 and x102 respectively and in swap() method only changing the references to the objects.
So, once the swap function execution ends the swap() stack memory will me vanished and the objects in heap are now available for garbage collection. See below image:
Once you back to main() scope, here circle and square still referencing to the original objects in heap. That?s how it works.
Now, What about the modification of object?
Since we have seen the behind the scene of object?s referencing. Lets took at a glance at the image below to understand the modification of objects from invoked method that reflects to original object in heap.
Any changes in the content of the object?s that is passed as formal argument to modify() method will go and find the the original/actual object and modify it. That?s how object modification works in java.
Don?t confuse with the ArrayList. It does not pass by reference. Its same like object modification process. when we pass ArrayList, then we use object?s methods (i.e. add() or remove() etc?) to modify the passed reference. ?
Are primitives types pass by value?
Yes, like object types, primitives are also passed by value. Since it does not contain any area in heap, its scope is only for the current stack memory. So, when we pass the primitives, the value is being copied and passed. BUT when we use wrapper class for primitives like Integer or Boolean, it?s considered as normal objects and object are slower than primitives. So, one main reason for the primitives in java is Performance and memory allocations.
Hope it will clear the concept of pass by value and pass by reference. If you have any query, please drop your message in the comments. Thanks. ?
If you are an Android developer, you may need to have a look at Android Build Variants