What are shallow copy and deep copy in Java?
In Java, the concepts of shallow copy and deep copy refer to two different ways of copying objects. Understanding these concepts is important for managing object references and ensuring that your program behaves as expected when dealing with mutable objects.
A shallow copy of an object is a new object that is a copy of the original object, but it only copies the references to the objects contained within the original object. This means that if the original object contains references to other objects, the shallow copy will reference the same objects rather than creating new copies of them.
In Java, you can create a shallow copy using the clone()
method (if the class implements the Cloneable
interface) or by using a copy constructor. Here's an example:
class Person implements Cloneable {
String name;
Address address; // Assume Address is another class
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // This creates a shallow copy
}
}
class Address {
String city;
public Address(String city) {
this.city = city;
}
}
// Usage
Person original = new Person("John", new Address("New York"));
Person shallowCopy = (Person) original.clone();
In this example, shallowCopy.address
will point to the same Address
object as original.address
. If you modify the Address
object through either original
or shallowCopy
, the changes will be reflected in both.
A deep copy, on the other hand, creates a new object and recursively copies all objects referenced by the original object. This means that the deep copy will have its own copies of all objects, and changes to the deep copy will not affect the original object and vice versa.
To create a deep copy, you typically need to implement a custom method that explicitly copies all mutable objects. Here's an example:
class Person implements Cloneable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone();
cloned.address = new Address(this.address.city); // Create a new Address object
return cloned;
}
}
// Usage
Person original = new Person("John", new Address("New York"));
Person deepCopy = (Person) original.clone();
In this example, deepCopy.address
is a new Address
object, so changes to deepCopy.address
will not affect original.address
.
When deciding between shallow and deep copies, consider the mutability of the objects involved and the desired behavior of your application.