What is CloneNotSupportedException
in Java?
CloneNotSupportedException
is a checked exception in Java that is thrown when the Object.clone()
method is called on an object that does not implement the Cloneable
interface.
Cloning in Java refers to creating an exact copy of an object using the clone()
method. However, not all objects are cloneable by default. If you call clone()
on an object that doesn’t implement the Cloneable
marker interface, Java throws a CloneNotSupportedException
.
Class Declaration
package java.lang;
public class CloneNotSupportedException extends Exception {
public CloneNotSupportedException() {
super();
}
public CloneNotSupportedException(String message) {
super(message);
}
}
This is a checked exception, meaning it must be handled using a try-catch
block or declared with a throws
clause.
What is the Cloneable
Interface?
The Cloneable
interface is a marker interface (an interface with no methods). It signals to the JVM that the class allows field-for-field copying using Object.clone()
. If a class doesn’t implement Cloneable
, calling clone()
on its object throws a CloneNotSupportedException
.
When Does CloneNotSupportedException
Occur?
- When
super.clone()
is called in a class that does not implementCloneable
- When a subclass inherits
clone()
but its parent hasn’t implementedCloneable
- When a custom
clone()
method tries to clone a non-cloneable object
Example 1: Triggering CloneNotSupportedException
This example shows what happens when you try to clone an object that does not implement Cloneable
.
class Person {
String name;
public Person(String name) {
this.name = name;
}
public Person clonePerson() throws CloneNotSupportedException {
return (Person) super.clone(); // Will throw CloneNotSupportedException
}
}
public class CloneFailDemo {
public static void main(String[] args) {
Person person1 = new Person("Alice");
try {
Person person2 = person1.clonePerson();
System.out.println("Cloned: " + person2.name);
} catch (CloneNotSupportedException e) {
System.out.println("CloneNotSupportedException caught: " + e.getMessage());
}
}
}
Expected Output
CloneNotSupportedException caught: null
Explanation
- The class
Person
does not implementCloneable
. - Calling
super.clone()
results inCloneNotSupportedException
. - We catch the exception and print an error message.
Example 2: Fixing the Exception by Implementing Cloneable
Let’s correct the above example by implementing Cloneable
and overriding clone()
properly.
class Person implements Cloneable {
String name;
public Person(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class CloneSuccessDemo {
public static void main(String[] args) {
Person person1 = new Person("Bob");
try {
Person person2 = (Person) person1.clone();
System.out.println("Cloned: " + person2.name);
} catch (CloneNotSupportedException e) {
System.out.println("Cloning failed: " + e.getMessage());
}
}
}
Expected Output
Cloned: Bob
Explanation
- We implement the
Cloneable
interface. - Override
clone()
and callsuper.clone()
inside it. - The cloning works, and the cloned object is created successfully.
Deep vs Shallow Copy
Java's default clone()
performs a shallow copy — it copies field values directly, including references. For a deep copy (duplicating nested objects), you must override clone()
and handle it manually.
Example: Shallow Copy
class Address {
String city;
Address(String city) {
this.city = city;
}
}
class Employee implements Cloneable {
String name;
Address address;
Employee(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // shallow copy
}
}
public class ShallowCloneDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Address addr = new Address("New York");
Employee emp1 = new Employee("Tom", addr);
Employee emp2 = (Employee) emp1.clone();
emp2.address.city = "Los Angeles";
System.out.println("Original Employee City: " + emp1.address.city);
System.out.println("Cloned Employee City: " + emp2.address.city);
}
}
Expected Output
Original Employee City: Los Angeles
Cloned Employee City: Los Angeles
Explanation: Both objects share the same Address
reference because it’s a shallow copy.
How to Handle CloneNotSupportedException
Option 1: Catch it
try {
Object copy = obj.clone();
} catch (CloneNotSupportedException e) {
System.err.println("Object cannot be cloned.");
}
Option 2: Declare it
public Object cloneObject() throws CloneNotSupportedException {
return super.clone();
}
Best Practices
- Always implement
Cloneable
if your class overridesclone()
. - Use
super.clone()
inside your overridden method. - Override
clone()
withprotected
orpublic
visibility. - Document whether your class supports cloning to avoid confusion.
Common Mistakes
- Not implementing
Cloneable
but callingsuper.clone()
- Relying on shallow copy when deep copy is needed
- Forgetting to handle
CloneNotSupportedException
in method calls
Summary
CloneNotSupportedException
is thrown when an object not implementingCloneable
is cloned.- It is a checked exception and must be handled.
- Implement
Cloneable
and overrideclone()
to enable object cloning. - Be mindful of shallow vs deep copying, especially with reference fields.
Final Thoughts
Understanding CloneNotSupportedException
is essential when working with object copying in Java. While cloning is not always the preferred way to duplicate objects (compared to copy constructors or serialization), knowing how it works helps in legacy projects, libraries, or performance-sensitive applications. Handle the exception correctly and choose the right copying method based on your application’s needs.