How is Java Pass by Value and Not by Reference

Java Pass by Value and Not by Reference

There is a common confusion in Java Developers especially who have worked with C/C++, whether Java is “Pass by Value” or “Pass by Reference”.

 

What is Pass by Value?

In Pass by Value, the method parameter values are copied to another variable and then the copied object is passed. Any changes that happen inside the method happen on this copy of the variable, which means that the value of the original parameter passed in the method will be unchanged outside the method scope.

What is Pass by Reference?

In Pass by Reference, an alias or reference to the actual parameter is passed to the method. As the actual method is passed, any changes made in the method on the parameter will be observed outside the method scope also.

 

Java is Strictly “Pass by Value”

 

Examples to prove Java Pass By Value

Let’s observe some examples and try to clear this confusion once and for all.

For the sake of simplicity, we will divide the clarification into 3 parts:

  1. Primitives
  2. Regular Objects
  3. Collection Objects

 

Primitive

 

public static void main(String[] args) {

    int number = 1;
    System.out.println("Main Method before the change(): " + number);
    change(number);
    System.out.println("Main Method after the change(): " + number);
}

public static void change(int number) {

    number = 10;

    System.out.println("Change Method: " + number);

}

OUTPUT:

Main Method before the change(): 1
Change Method: 10
Main Method after the change(): 1

 

It is very obvious that in the above code, Java has passed the 10 in variable number instead of passing the reference of variable number.

So any change in number inside method change, will not impact variable number outside the change method.

 

Regular Objects

 

package com.adevguide.java.generic;

public class PassByValueReference {

    public static void main(String[] args) {
        Vehicle car = new Vehicle("4-Wheeler", "Mercedes G", "Black");
        Vehicle bike = new Vehicle("2-Wheeler", "Yamaha FZS", "Yellow-Green");

        System.out.println("Before the Swap: ");
        System.out.println("Car(v1) name: " + car.getName());
        System.out.println("Bike(v2) Color: " + bike.color);
        swap(car, bike);

        System.out.println("After the Swap: ");
        System.out.println("Car(v1) name: " + car.getName());
        System.out.println("Bike(v2) Color: " + bike.color);

    }

    public static void swap(Vehicle v1, Vehicle v2) {

        Vehicle temp = v1; // Creating Temp Vehicle object
        v1 = v2; // Swapping v1 and v2
        v2 = temp;

        System.out.println("Inside swap: v1 color: " + v1.getName());
        System.out.println("Inside swap: v2 color: " + v2.getName());

    }

}

class Vehicle {
    private String type;
    private String name;
    String color;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Vehicle(String type, String name, String color) {
        this.type = type;
        this.name = name;
        this.color = color;
    }

}

 

Output:

Before the Swap: 
Car(v1) name: Mercedes G
Bike(v2) Color: Yellow-Green
Inside swap: v1 color: Yamaha FZS
Inside swap: v2 color: Mercedes G
After the Swap: 
Car(v1) name: Mercedes G
Bike(v2) Color: Yellow-Green

 

When I said that Java is strictly passed by value, I meant it. As we cannot directly pass the value of an object just like primitives in the method, Java passes the reference of the parameter as value.

Java manipulates objects ‘by reference,’ but it passes object references to methods ‘by value’.

For simplicity, you can think that Java always creates a new object for every parameter type and then assign the actual reference of the parameter to this.
So any changes (like swap) made to this method parameter will be valid only inside the scope of the method.

In our example, v1 has a reference same as the car and v2 has a reference same as the bike. Now once the swap is performed inside the method, v1 has the same reference as the bike and v2 has the same reference as the bike.

As the scope of v1 and v2 is only inside method swap(), the values of car and bike objects are still intact.

How is Java Pass by Value and Not Reference

 

When instead of a swap if we try to alter the value of the object, the changes will be available outside the method also because the changes will be made to the reference of the object which is passed as value.

 

package com.adevguide.java.generic;

public class PassByValueReference {

    public static void main(String[] args) {
        Vehicle car = new Vehicle("4-Wheeler", "Mercedes G", "Black");
        Vehicle bike = new Vehicle("2-Wheeler", "Yamaha FZS", "Yellow-Green");

        Vehicle oldCar = car;
        Vehicle oldBike = bike;

        System.out.println("Before the change: ");
        System.out.println("Car(v1) is:  " + car.toString());
        System.out.println("Bike(v2) Color: " + bike.toString());
        change(car, bike);

        System.out.println("After the change: ");
        System.out.println("Car(v1) is: " + car.toString());
        System.out.println("Bike(v2) is: " + bike.toString());

        System.out.println(oldCar == car); // true
        System.out.println(oldBike == bike); // true

    }

    public static void change(Vehicle v1, Vehicle v2) {

        v1.setName("Honda Jazz"); // v1 is pointing towards car

        Vehicle temp = v1; // Creating Temp Vehicle object

        v2.setName("Pulsur"); //// v1 is pointing towards bike
        v1 = v2; // Swapping v1 and v2
        v1.color = "Green"; // v1 is pointing towards bike
        v2 = temp; // v2 is pointing towards car
        v2.color = "red"; //// v1 is pointing towards car

        System.out.println("Inside swap: v1 is: " + v1.toString());
        System.out.println("Inside swap: v2 is: " + v2.toString());

    }

}

class Vehicle {
    private String type;
    private String name;
    String color;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Vehicle(String type, String name, String color) {
        this.type = type;
        this.name = name;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Vehicle [type=" + type + ", name=" + name + ", color=" + color + "]";
    }

}

 

Output:

Before the change:
Car(v1) is: Vehicle [type=4-Wheeler, name=Mercedes G, color=Black]
Bike(v2) Color: Vehicle [type=2-Wheeler, name=Yamaha FZS, color=Yellow-Green]
Inside swap: v1 is: Vehicle [type=2-Wheeler, name=Pulsur, color=Green]
Inside swap: v2 is: Vehicle [type=4-Wheeler, name=Honda Jazz, color=red]
After the change:
Car(v1) is: Vehicle [type=4-Wheeler, name=Honda Jazz, color=red]
Bike(v2) is: Vehicle [type=2-Wheeler, name=Pulsur, color=Green]

 

In the above example, the change function is just a little modification of swap function. As I said before, Object v1 and v2 have a reference to car and bike.

Swap changes the reference of v1 to the bike and v2 to the car inside the method scope but they always point to one of these two objects. So changes made to v1 and v2 will always alter the value of the object it has a reference at that time.

Even the values of the object have changed now, but as OldCar and car are still pointing towards the same object, oldCar==car will return true.

All About Java Regular Expressions Regex 2019

 

 

Java Pass By value Object

 

Collections Objects

Collections like List, Map, Set follows the same rules as a regular object.

package com.adevguide.java.generic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PassByValueReference {

    public static void main(String[] args) {

        Map<String, Integer> map = new HashMap<String, Integer>();

        map.put("A", 1);
        map.put("B", 2);

        List<Integer> list = new ArrayList<Integer>();
        list.add(10);
        list.add(20);

        System.out.println("map Before the Change(): " + map);
        System.out.println("list Before the Change(): " + list);

        change(map, list);

        System.out.println("map After the Change(): " + map);
        System.out.println("list After the Change(): " + list);

    }

    public static void change(Map m1, List l1) {
        m1.put("C", 3);
        l1.add(30);

        Map<String, Integer> newMap = new HashMap<String, Integer>();

        newMap.putAll(m1);
        newMap.put("D", 4);

        List<Integer> newList = new ArrayList<Integer>();
        newList.addAll(l1);
        newList.add(40);

        Map<String, Integer> lastMap = m1;
        List<Integer> lastList = l1;

        lastMap.remove("A");
        lastList.remove(0);

        System.out.println("Inside Change Method:");
        System.out.println("m1 is: " + m1);
        System.out.println("newMap is : " + newMap);
        System.out.println("lastMap is : " + lastMap);

        System.out.println("l1 is : " + l1);
        System.out.println("newList is : " + newList);
        System.out.println("lastList is : " + lastList);

    }

}

Output:

map Before the Change(): {A=1, B=2}
list Before the Change(): [10, 20]
Inside Change Method:
m1 is: {B=2, C=3}
newMap is : {A=1, B=2, C=3, D=4}
lastMap is : {B=2, C=3}
l1 is : [20, 30]
newList is : [10, 20, 30, 40]
lastList is : [20, 30]
map After the Change(): {B=2, C=3}
list After the Change(): [20, 30]

 

As we can see, map,m1, and lastMap have a common reference to an object whereas newMap points towards a different object. This means any changes made to either of map,m1, and lastMap will reflect in others too. Whereas newMap is independent of these changes.

 

Similarly, list,l1, and lastList have a common reference to an object whereas newList points towards a different object. This means any changes made to either of map,m1, and lastMap will reflect in others too. Whereas newList is independent of these changes.

 

Java Pass By Value Tutorial Source Code

You can find the complete source code used in this tutorial on Github.

GitHub Source Code

 

References

https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html