Java Pass by Reference vs Pass by Value Example
In this post, we feature a comprehensive Java Pass by Reference vs Pass by Value Example.
1. Introduction
There are two ways to pass arguments (parameters) into methods (functions) in most programming languages:
- Pass by Reference – A reference to the actual parameter is passed to the method. If the method modifies the parameter variable, the changes are visible to the caller.
- Pass by Value – The method parameter values are copied to another variable and then the copied value is passed. If the method modifies the parameter variable, the changes are not visible to the caller.
Java only supports “Pass by Value”. When an object is passed as an argument to a method, the reference to that object is passed.
Java manipulates objects by reference, and all object variables are references. Java new
keyword creates a space in memory to hold the object structure and assigns a reference variable to the memory address.
In this example, I will demonstrate how Java passes the argument by value and how the object reference is passed to a method.
2. Technologies Used
The example code in this article was built and run using:
- Java 11
- Eclipse Oxygen
3. DataObject
In this step, I will create a DataObject
class which has three data members: a number
with the int
type, a charValue
with the char
type, and a name
with the String
type.
It has three setters which sets the values for the data member and then modifies the argument’s value. It overrides the toString
method to print out the object’s contents.
DataObject.java
package org.jcg.zheng; public class DataObject { private char charValue; private String name; private int number; public char getCharValue() { return charValue; } public String getName() { return name; } public int getNumber() { return number; } public void setCharValue(char charValue) { this.charValue = charValue; charValue = 'X'; System.out.println("\tUpdate charValue inside setCharValue, charValue=" + charValue); } public void setName(String name) { this.name = name; name = "Dummy" + name; System.out.println("\tUpdate name inside setName, name=" + name); } public void setNumber(int number) { this.number = number; number = number - 99; System.out.println("\tUpdate argument number inside setNumber, number=" + number); } @Override public String toString() { return "DataObject [number=" + number + ", charValue=" + charValue + ", name=" + name + "]"; } }
4. PassByValueTest
In this step, I will create a PassByValueTest
to demonstrate Java’s “Pass by Value” and “Object Reference”.
First, I will create three private methods:
changeObject (DataObject dObj)
– Invokes the setter to update the object’s contents. Although A method cannot change the reference itself, but it can change the object pointed to by the reference.displayObjectIdentity (DataObject dObj)
– Prints out the object’shashcode
and its contents. Java hides the actual memory address, so I will use theSystem.identityHashCode
to identify the objects.reAssignObject (DataObject dObj)
– Re-assign the object reference passed from an argument to a different value.
I will create three test methods:
pass_by_value_with_primitive_type
– The primitive arguments changed by the setters are not visible to the caller.pass_by_value_with_object
– The object reference argument changed by the functionreAssignObject
is not visible to the caller.pass_by_value_with_object_2
– The object’s reference is not changed but the object content is changed by the functionchangeObject
.
PassByValueTest.java
package org.jcg.zheng; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.Objects; import org.junit.Test; public class PassByValueTest { private void changeObject(DataObject dObj) { dObj.setName("Mary"); dObj.setNumber(dObj.getNumber() + 1); } private void displayObjectIdentity(DataObject dObj) { System.out.println("\tidentityHashCode=" + System.identityHashCode(dObj) + ". Content=" + dObj.toString()); } private void reAssignObject(DataObject dObj) { System.out.println("Start reAssignObject:"); displayObjectIdentity(dObj); // create a new DataObject object and create a temp with the object's reference value DataObject temp = new DataObject(); dObj = temp; System.out.println("Completed reAssignObject:"); displayObjectIdentity(dObj); assertTrue(Objects.equals(dObj, temp)); } @Test public void pass_by_value_with_object() { DataObject dObj = new DataObject(); dObj.setNumber(2); dObj.setCharValue('B'); dObj.setName("Zheng"); System.out.println("Before reAssignObject:"); displayObjectIdentity(dObj); reAssignObject(dObj); System.out.println("After reAssignObject:"); displayObjectIdentity(dObj); assertEquals("Zheng", dObj.getName()); assertEquals(2, dObj.getNumber()); assertEquals('B', dObj.getCharValue()); } @Test public void pass_by_value_with_object_2() { DataObject dObj = new DataObject(); dObj.setNumber(2); dObj.setCharValue('B'); dObj.setName("Zheng"); System.out.println("Before changeObject:"); displayObjectIdentity(dObj); changeObject(dObj); System.out.println("After changeObject:"); displayObjectIdentity(dObj); assertEquals("Mary", dObj.getName()); assertEquals(3, dObj.getNumber()); assertEquals('B', dObj.getCharValue()); } @Test public void pass_by_value_with_primitive_type() { String mary = "Mary"; int oneNum = 1; char charA = 'A'; DataObject dObj = new DataObject(); dObj.setNumber(oneNum); dObj.setCharValue(charA); dObj.setName(mary); assertEquals("Mary", mary); assertEquals(1, oneNum); assertEquals('A', charA); } }
Note: changeObject
, since the object’s reference is passed to the method as an argument, we can invoke the object’s setName
to update the object’s name property.
Junit Output
C:\MaryZheng\Workspaces\java-pass-by-value>mvn install test [INFO] Scanning for projects... [INFO] [INFO] --------------------< java-demo-pbv:java-demo-pbv >--------------------- [INFO] Building java-demo-pbv 0.0.1-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ java-demo-pbv --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory C:\MaryZheng\Workspaces\java-pass-by-value\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ java-demo-pbv --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 2 source files to C:\MaryZheng\Workspaces\java-pass-by-value\target\classes [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ java-demo-pbv --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory C:\MaryZheng\Workspaces\java-pass-by-value\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ java-demo-pbv --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ java-demo-pbv --- [INFO] Surefire report directory: C:\MaryZheng\Workspaces\java-pass-by-value\target\surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Running org.jcg.zheng.PassByValueTest Update argument number inside setNumber, number=-97 Update charValue inside setCharValue, charValue=X Update name inside setName, name=DummyZheng Before reAssignObject: identityHashCode=532854629. Content=DataObject [number=2, charValue=B, name=Zheng] Start reAssignObject: identityHashCode=532854629. Content=DataObject [number=2, charValue=B, name=Zheng] Completed reAssignObject: identityHashCode=388043093. Content=DataObject [number=0, charValue= , name=null] After reAssignObject: identityHashCode=532854629. Content=DataObject [number=2, charValue=B, name=Zheng] Update argument number inside setNumber, number=-97 Update charValue inside setCharValue, charValue=X Update name inside setName, name=DummyZheng Before changeObject: identityHashCode=266437232. Content=DataObject [number=2, charValue=B, name=Zheng] Update name inside setName, name=DummyMary Update argument number inside setNumber, number=-96 After changeObject: identityHashCode=266437232. Content=DataObject [number=3, charValue=B, name=Mary] Update argument number inside setNumber, number=-98 Update charValue inside setCharValue, charValue=X Update name inside setName, name=DummyMary Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.217 sec Results : Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 9.494 s [INFO] Finished at: 2019-03-23T17:52:46-05:00 [INFO] ------------------------------------------------------------------------ C:\MaryZheng\Workspaces\java-pass-by-value>
5. Java Pass by Reference vs Pass by Value Example – Summary
In this example, I created a DataObject
class and three test cases to demonstrate how Java “pass by value” works. Java always passes by value for the parameters and always stores the object’s reference as a value.
Java and C languages support “Pass By Value” only. C++ supports both “Pass by Value” and “Pass by Reference”.
6. Download the Source Code
This example consists of a project with two classes: DataObject
and PassByValueTest
to demonstrate the Java’s “Pass by Value” and “Object Reference”.
You can download the full source code of this example here: Java Pass by Reference vs Pass by Value Example
Last updated on Aug. 13, 2019
Thank you