Before describing how arguments are passed in java, it is worth to define how java variables are allocated inside the memory. Basically we talk about 2 types of variables: primitives and objects.
Primitive variables are always stored inside the stack memory (the memory space which holds method specific variables that are short-lived, in addition to references to other objects in the heap) , however in case of objects, they are stored at 2 stages, the actual object data is stored inside the heap memory (the memory space which holds objects and JRE classes) and a reference for the object is kept inside stack memory which just points to the actual object.
1. By value VS By reference
What is meant by “By value” and “By reference”:
- By value: when arguments are passed by value to a method, it means that a copy of the original variable is being sent to the method and not the original one, so any changes applied inside the method are actually affecting the copy version.
- By reference: When arguments are passed by reference, it means that a reference or a pointer to the original variable is being passed to the method and not the original variable data.
2. How arguments are passed in java?
In java, arguments are always passed by value regardless of the original variable type. Each time a method is invoked, the following happens:
- A copy for each argument is created in the stack memory and the copy version is passed to the method.
- If the original variable type is primitive, then simply, a copy of the variable is created inside the stack memory and then passed to the method.
- If the original type is not primitive, then a new reference or pointer is created inside the stack memory which points to the actual object data and the new reference is then passed to the method, (at this stage, 2 references are pointing to the same object data).
3. Fixing some concerns !!
In the following example, we try to validate that “java is always pass by value” through passing several argument types (primitive, wrappers, collections, business objects) and checking whether they are modified after the method call.
- Passing primitive arguments:
Output Description:The 2 variables x & y are of primitive types and they are stored inside the stack memory. When calling modifyPrimitiveTypes(), 2 copies are created inside the stack memory (let’s say w & z) and then passed to the method. Hence original variables are not being sent to the method and any modification inside the method flow is affecting only the copies.
Passing wrapper arguments:
Output:
Output Description:
Output:
Output Description:
Output:
Output Description:
Wrappers are stored inside the heap memory with a correspondent reference inside the stack memory.
When calling modifyWrappers(), a copy for each reference is created inside the stack memory and the copies are passed to the method. Any change on the reference inside the method is actually changing the reference of the copies and not the original references.
Passing Collection argument:
Output:
Output Description:
When defining an Arraylist or any collection in java, a reference is created inside the stack which points to multiple objects inside the heap memory, when calling modifyList(), a copy of the reference is created and passed to the method, so that the actual object data is referenced by 2 references and any change done by one reference is reflected on the other.
Inside the method, we called lstParam.add(2) , which actually tries to create a new Integer object in the heap memory and link it to the existing list of objects . Hence the original list reference can see the modification since both references are pointing to the same object in memory.
Passing business object as argument:
Output:
Output Description:
The student object is created inside the heap space and a reference for it is defined inside the stack, when calling modifyStudent(), a copy of the reference is created inside the stack and passed to the method. Any modifications on the object attributes inside the method is reflected on the original reference.
4. Conclusion
In java, arguments are always passed by value , the copy would be either a reference or a variable depending on the original variable type. From now on, you can use the following tips in order to understand how modifying arguments inside the method affect the original variable:
- Modifying the value of a primitive argument would never affect the original variable.
- Changing the reference of an object argument inside the method would never affect the original reference, however it creates a completely new object in the heap space.
- Modifying the attributes of the object argument inside the method is reflected outside it.
- Modifying collections & maps inside the method is reflected outside it.
No comments:
Post a Comment