The Cloneable interface in Java is a marker interface that indicates a class supports object cloning. It works with the Object.clone() method to create a copy of an existing object instead of creating a new one manually.
- It is a marker interface and contains no methods.
- Belongs to the java.lang package.
Example: Implementing Cloneable interface to allow object cloning using Shallow Cloning
class Person implements Cloneable {
String name;
int age;
// Constructor to initialize object fields
Person(String name, int age){
this.name = name;
this.age = age;
}
// Overriding clone() by simply calling super.clone()
// enables shallow copy using Object's clone method
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Geeks {
public static void main(String[] args) {
try {
// Create original object
Person p1 = new Person("Alice", 25);
// Clone the original object
Person p2 = (Person) p1.clone();
// Display original and cloned object details
System.out.println("Original: " + p1.name + ", " + p1.age);
System.out.println("Clone: " + p2.name + ", " + p2.age);
// Modify the clone to show both objects are separate
p2.name = "Bob";
System.out.println("After modification:");
// Original remains unchanged
System.out.println("Original: " + p1.name);
// Clone has new value
System.out.println("Clone: " + p2.name);
}
catch (CloneNotSupportedException e)
{
// Handle exception if object cloning is not supported
e.printStackTrace();
}
}
}
Output
Original: Alice, 25 Clone: Alice, 25 After modification: Original: Alice Clone: Bob
Explanation: In this example, the Person class implements the Cloneable interface and overrides the clone() method by calling super.clone(). This creates a shallow copy of the object. After cloning, modifying the cloned object's name does not affect the original object because both objects are separate instances.
Syntax
class ClassName implements Cloneable {
// class fields and methods
}
Example 2: Deep Copy Example
// Address class used as a nested object
class Address {
String city;
Address(String city) {
this.city = city;
}
// Copy constructor for deep copying
Address(Address addr) {
this.city = addr.city;
}
}
// Person class implementing deep cloning
class Person implements Cloneable{
String name;
Address address;
Person(String name, Address address){
this.name = name;
this.address = address;
}
// Overriding clone() for deep copy
@Override
protected Object clone() throws CloneNotSupportedException{
// Create new Address object to achieve deep copy
Person cloned = (Person) super.clone();
cloned.address = new Address(this.address);
return cloned;
}
}
public class DeepCloneExample{
public static void main(String[] args){
try {
// Create original object
Person p1 = new Person("Alice", new Address("New York"));
// Clone original object
Person p2 = (Person) p1.clone();
// Modify clone’s nested object
p2.address.city = "London";
System.out.println("Original City: " + p1.address.city);
System.out.println("Clone City: " + p2.address.city);
}
catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
Output
Original City: New York Clone City: London
Explanation: In this example, the Person object contains an Address object. During cloning, a new Address object is created using a copy constructor, ensuring the original and cloned objects have separate nested objects. Therefore, changing the cloned object's address does not affect the original object's address.
Advantages of Cloneable
- Easy Object Copying: Creates duplicate objects without manually copying each field.
- Improves Performance: Faster than creating a new object and assigning values one by one.
- Supports Custom Cloning: Allows implementation of both shallow and deep copying.
- Useful in Prototype Design: Helps create multiple object copies efficiently from an existing object.
- Reduces Code Duplication: Eliminates repetitive object initialization code