In Java, copy an object is not an easy task as it looks like. Most of us makes this mistake during the initial days of our development carreer. In Java, objects are not passed by value. For example, let’s take a look at the program below :
public class Main {
public static void main(String[] args) {
//1
Car myCar = new Car("XeX", 4);
Car yourCar = myCar;
//2
yourCar.setCarName("YeY");
yourCar.setCarWheels(2);
//3
System.out.println("myCar name : " + myCar.getCarName());
System.out.println("myCar wheels : " + myCar.getCarWheels());
System.out.println("yourCar name : " + yourCar.getCarName());
System.out.println("yourCar wheels : " + yourCar.getCarWheels());
}
}
class Car {
private String carName;
private int carWheels;
Car(String name, int wheels) {
this.carName = name;
this.carWheels = wheels;
}
int getCarWheels() {
return carWheels;
}
String getCarName() {
return carName;
}
void setCarName(String carName) {
this.carName = carName;
}
void setCarWheels(int carWheels) {
this.carWheels = carWheels;
}
}
What we are doing here :
The commented numbers in the above program denote the step number below :
-
First of all, we have created one Car object myCar. Then we have created one more Car object yourCar and then assign the value of myCar to yourCar using ’=’ operator. At first it looks like both are different objects with different values on memory. But is it?
-
To find out, if both are totally different objects or not, change the value of name and wheels for the yourCar variable.
-
Finally, print out the values of name and wheels for each objects. It should be different , isn’t it ? The output will look like as below :
myCar name : YeY
myCar wheels : 2
yourCar name : YeY
yourCar wheels : 2
As you can see changing values of one object also change the values of the other object. That means ’=’ operator doesn’t copy content of one object of one to another.
Deep copy, how to do it in Java :
The first question comes to our mind is what is a deep copy and is there any copy operation available in Java !
We can categorized copy operation in two types in Java : deep copy and shallow copy. Shallow copy uses bit wise copy of an object. Suppose, your myCar object contains the following variables :
private String carName;
private Car car;
Now, if we do shallow copy and create different variable yourCar copying contents of myCar, it will copy the string carName and create one different string for the new variable. But, since the car variable holds only the reference to an object of type Car, it will copy the same reference to the new variable. So, if you make any change to the Car variable in any object, it will reflect on both.
Unlike shallow, deep copy copies all contents and creates different contents for both variables.
In this tutorial, we will learn how to do deep copy using SerializationUtils class.
Example of deep copy using SerializationUtils :
Maven configuration :
org.apache.commons
commons-lang3
3.7
Gradle configuration :
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.7'
Check this link for updated build info. Source code :
import org.apache.commons.lang3.SerializationUtils;
import java.io.Serializable;
public class Main {
public static void main(String[] args) {
//2
Car car1 = new Car("XeX");
CarInfo car1Info = new CarInfo(1, car1);
//3
CarInfo car2Info = SerializationUtils.clone(car1Info);
car2Info.setId(2);
car2Info.setCar(new Car("YeY"));
//4
System.out.println("car1Info id : " + car1Info.getId());
System.out.println("car1Info carName : " + car1Info.getCar().getCarName());
System.out.println("car2Info id : " + car2Info.getId());
System.out.println("car2Info carName : " + car2Info.getCar().getCarName());
}
}
//1
class CarInfo implements Serializable {
private int id;
private Car car;
CarInfo(int id, Car car) {
this.id = id;
this.car = car;
}
void setCar(Car car) {
this.car = car;
}
void setId(int id) {
this.id = id;
}
Car getCar() {
return car;
}
int getId() {
return id;
}
}
class Car implements Serializable {
private String carName;
Car(String name) {
this.carName = name;
}
String getCarName() {
return carName;
}
}
Explanation :
The commented numbers in the above program denote the step number below :
-
We have two model classes in this example. Car class contains the String carName. CarInfo class contains two variables. One is integer variable id and the other one is a Car variable car. One thing we should note that both classes implements Serializable interface.
-
First of all, we have created one CarInfo object car1Info with id 1 and one Car object with carName XeX.
-
For deepcopy, we are using SerializationUtils.clone() method. We have used deepcopy to clone all contents of car1Info to car2Info. Then we are changing the contents of car2Info just to make sure that all contents are copied without any reference to the car2Info objects.
-
Finally, similar to the previous example, we are printing out the contents of the car1Info and car2Info objects. This program will print the following output :
Output :
car1Info id : 1
car1Info carName : XeX
car2Info id : 2
car2Info carName : YeY
As you can see, the changes in the car2Info object doesn’t impact on car1Info object. That means all items in car2Info is different than car1Info.
Conclusion :
In this tutorial, we have learn the difference between shallow copy and deep copy. Also, how to implement deep copy using SerializationUtils in Java. Always make sure to implement Serializable in the object classes while using SerializationUtils. Try to run the code and drop a comment below if you have any queries.