Cloning an object in Java means making a new object with the same field values as an existing one. The built-in way is for the class to implement the Cloneable interface and override clone(), which calls super.clone(). For classes we write ourselves, a copy constructor or a static factory method such as copyOf() is the recommended way, because the copy then goes through a normal constructor like any other new object.
We clone an object when code must change a copy without touching the original, for example when a music app lets a user duplicate a playlist and edit the duplicate.
The following example shows both ways, followed by the difference between a shallow and a deep clone(), with the result of each line as a comment.
// 1. Cloneable + clone() that calls super.clone()
public class Song implements Cloneable {
@Override
public Song clone() {
try {
return (Song) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e); // cannot happen, Song is Cloneable
}
}
}
Song original = new Song("Yellow", 10);
Song cloned = original.clone(); // Song[title=Yellow, plays=10]
boolean same = cloned == original; // false (a new object)
// 2. Recommended: copy constructor or static factory method
public Song(Song other) { this(other.title, other.plays); }
public static Song copyOf(Song other) { return new Song(other.title, other.plays); }
Song copied = new Song(original); // Song[title=Yellow, plays=10]
Song factoryCopy = Song.copyOf(original); // Song[title=Yellow, plays=10]
cloned.setPlays(99);
int plays = original.getPlays(); // 10 (the copies are independent)
// 3. super.clone() alone is shallow: nested objects are shared
ShallowPlaylist shallowCopy = shallowOriginal.clone(); // clone() = super.clone() only
shallowCopy.getSongs().getFirst().setPlays(99);
int sharedPlays = shallowOriginal.getSongs().getFirst().getPlays(); // 99 (same Song object)
Playlist deepCopy = deepOriginal.clone(); // clone() also copies the list and songs
deepCopy.getSongs().getFirst().setPlays(99);
int ownPlays = deepOriginal.getSongs().getFirst().getPlays(); // 10 (a separate Song object)
Notice that the shallow copy changes the song of the original playlist to 99 plays, whereas the deep copy leaves it at 10.
Next, we look at the difference between a shallow and a deep copy, at the CloneNotSupportedException that a missing Cloneable causes, and at cloning arrays and collections. After that, we compare four ways to make a deep copy (copy constructors, clone(), serialization and Jackson), see why records and immutable objects need no copy at all, and why Effective Java advises against Cloneable for new classes.
1. What Is Object Cloning in Java?
Assigning an object to a second variable does not copy the object. After Song b = a;, both variables point to the same Song object, so a change made through b is visible through a. A clone is different, because it is a second object in memory, created from the state of the first one.
1.1. Cloneable and Object.clone()
Cloning in Java needs two pieces that work together, an interface and a method of the Object class.
- Cloneable is a marker interface (that is, an interface with no methods at all). A class implements Cloneable only to tell Object.clone() that copying is allowed.
- Object.clone()) is a protected method of the Object class, so a subclass can call it but other code cannot. It creates a new object of the same class as the original and then copies every field “as if by assignment”, without running any constructor.
The method clone() is declared in Object, not in Cloneable, so implementing the interface alone gives a class no public clone() method. The class must also override clone() and make the method public.
The JavaDoc of Object.clone() describes the expected result with three checks, but only the first check is a firm rule, and the JavaDoc calls the other two “not absolute requirements”.
boolean separate = cloned != original; // true: a separate object
boolean sameClass = cloned.getClass() == original.getClass(); // true: same class, if every class calls super.clone()
boolean equal = cloned.equals(original); // false here: Song does not override equals()
The last line is false because Object.equals() compares references, and the clone is a separate object. A class that wants equals() to return true for a clone has to override equals() and hashCode().
1.2. Shallow Copy vs Deep Copy
The method Object.clone() copies field values. For a primitive field such as int plays, the value is the number itself, so the clone gets its own copy of the number.
For a reference field such as List<Song> songs, the value is a reference that points to the list, so the clone points to the same list as the original. A copy that shares the referenced objects with the original is called a shallow copy.
A deep copy goes further and also copies every mutable object (an object whose state can change, such as a List) that the original refers to. After a deep copy, the two objects share nothing that can change.

The main difference between the two copies is what happens to mutable fields, such as a list or an array.
| Shallow copy | Deep copy | |
|---|---|---|
| Primitive fields (int, double) | Copied | Copied |
| Immutable fields (String, Integer, records) | Shared, which is safe | Shared, which is safe |
| Mutable fields (List, arrays, Song) | Reference shared | New object with copied state |
| A change to a nested object | Visible in both objects | Visible only in one object |
| Made by default by | super.clone(), array.clone(), ArrayList.clone() | Our own code, serialization, Jackson |
| Cost | One new object | One new object for every mutable object reached |
Fields that hold immutable objects (objects that cannot change after they are created) never need a deep copy. A String field can stay shared, because nobody can change the String.
2. Cloning an Object With clone()
The following example is a small music app, where a Song has a title and a plays counter, and a Playlist has a name and a List<Song>.
The complete code, including the CloningDemo class that prints every result in the snippets, is in the Core-Java repository on GitHub. The code is compiled for Java 21 and run on JDK 25.
2.1. Implementing Cloneable and Overriding clone()
A good clone() override has three parts, and the first one decides whether super.clone() works at all.
- Implement Cloneable, because without the interface, super.clone() throws CloneNotSupportedException.
- Make the method public and return the class type, Song instead of Object. Java allows an override to return a narrower type (called a covariant return type), so the caller needs no cast.
- Catch CloneNotSupportedException inside the method. It is a checked exception, which the compiler forces callers to catch or declare, but for a Cloneable class it cannot happen, so callers should not have to handle it.
public class Song implements Cloneable {
private String title;
private int plays;
@Override
public Song clone() {
try {
return (Song) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError("Song implements Cloneable", e);
}
}
}
Song needs nothing more than super.clone(), because the title field is an immutable String and plays is a primitive. So a clone of Song is already independent, and after cloned.setPlays(99), original.getPlays() still returns 10.
2.2. CloneNotSupportedException When Cloneable Is Missing
The method Object.clone() checks for the interface while the program runs, not when the code compiles. Our Podcast class overrides clone() but does not implement Cloneable, so the code compiles and throws CloneNotSupportedException on the first call.
public class Podcast { // no "implements Cloneable"
@Override
public Podcast clone() throws CloneNotSupportedException {
return (Podcast) super.clone();
}
}
Podcast copy = new Podcast("Lokesh").clone(); // CloneNotSupportedException
java.lang.CloneNotSupportedException: com.howtodoinjava.cloning.Podcast
The message is only the class name. When a CloneNotSupportedException names one of our classes, that class or one of its parents is missing implements Cloneable. Because a subclass inherits Cloneable from its parent, adding the interface to the parent fixes all subclasses.
2.3. The Shallow Copy Problem
ShallowPlaylist clones itself with super.clone() only. The name field is not a problem, because when we call setName() on the copy, the copy gets a new String reference and the original keeps its own. The songs list is different, because both objects share the list.
@Override
public ShallowPlaylist clone() {
try {
return (ShallowPlaylist) super.clone(); // copies the reference to the same list
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
ShallowPlaylist copy = original.clone();
copy.setName("Gym");
copy.add(new Song("Clocks", 3));
copy.getSongs().getFirst().setPlays(99);
String name = original.getName(); // Road Trip
List<Song> songs = original.getSongs(); // [Song[title=Yellow, plays=99], Song[title=Clocks, plays=3]]
boolean sameList = copy.getSongs() == original.getSongs(); // true
The original playlist has a song it never added, and its Yellow song also shows 99 plays. In a real app, the user duplicates the “Road Trip” playlist as “Gym”, adds a song to the gym playlist, and finds the same song in the road trip playlist. The bug shows up far from the clone() call, which makes it hard to find.
2.4. Deep Copy in clone()
For a deep copy, clone() calls super.clone() and then copies every mutable field. Playlist.clone() gives the clone a new list and fills it with a clone of each song.
@Override
public Playlist clone() {
try {
Playlist copy = (Playlist) super.clone(); // 1. field-by-field copy
copy.songs = new ArrayList<>(); // 2. a new list
for (Song song : songs) {
copy.songs.add(song.clone()); // 3. a clone of every song
}
return copy;
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
When we run the same test as in section 2.3, the original no longer changes.
Playlist copy = original.clone();
copy.add(new Song("Clocks", 3));
copy.getSongs().getFirst().setPlays(99);
List<Song> originalSongs = original.getSongs(); // [Song[title=Yellow, plays=10]]
List<Song> copySongs = copy.getSongs(); // [Song[title=Yellow, plays=99], Song[title=Clocks, plays=3]]
boolean sameList = copy.getSongs() == original.getSongs(); // false
A deep clone() has to follow a few rules, and the last one is the easiest to miss.
- Primitive fields and immutable fields need no extra work.
- Every mutable field must be copied. If the field’s class supports cloning, we call clone() on the field; if not, we create a new object and copy the state into it.
- The copy must go all the way down. If Song held a mutable object and Song.clone() did not copy it, Playlist.clone() would still be shallow.
2.5. final Fields Cannot Be Cloned Deeply
The deep copy in Playlist.clone() assigns a new list to copy.songs after super.clone(). When the field is final, that assignment does not compile, because Java lets us set a final field only in a constructor or an initializer.
private final List<String> tracks = new ArrayList<>();
@Override
public FinalFieldClone clone() throws CloneNotSupportedException {
FinalFieldClone copy = (FinalFieldClone) super.clone();
copy.tracks = new ArrayList<>(tracks);
return copy;
}
FinalFieldClone.java:10: error: cannot assign a value to final variable tracks
copy.tracks = new ArrayList<>(tracks);
^
1 error
The class has two choices. It either removes final from the field, or it skips clone() and copies through a constructor.
Our Album class keeps private final List<Song> tracks and uses a copy constructor, as section 4 explains. Removing final only to make clone() work makes the class weaker, so the constructor is the better choice.
3. Cloning Arrays and Collections
Arrays and most JDK collections already have a working copy method, but all of these methods make a shallow copy.
3.1. array.clone() Is a Shallow Copy
Every array implements Cloneable, and the clone() method of an array is public and returns the same array type, so no cast is needed. For an array of primitives such as int[], a shallow copy is all we need. For an array of objects, the new array holds the same object references, so both arrays point to the same Song objects.
int[] plays = {10, 3, 7};
int[] playsCopy = plays.clone();
playsCopy[0] = 99;
String playsText = Arrays.toString(plays); // [10, 3, 7]
Song[] songs = {new Song("Yellow", 10), new Song("Clocks", 3)};
Song[] songsCopy = songs.clone();
boolean sameArray = songsCopy == songs; // false (a new array)
boolean sameSong = songsCopy[0] == songs[0]; // true (the same Song objects)
songsCopy[0].setPlays(99);
int firstPlays = songs[0].getPlays(); // 99
Song[] deepSongs = Arrays.stream(songs).map(Song::clone).toArray(Song[]::new);
boolean sameDeepSong = deepSongs[0] == songs[0]; // false
A two-dimensional array is an array of arrays, so clone() copies only the outer array. The rows stay shared, so we clone each row for a deep copy.
int[][] grid = {{1, 2}, {3, 4}};
int[][] gridCopy = grid.clone();
gridCopy[0][0] = 99;
int first = grid[0][0]; // 99 (the rows are shared)
int[][] gridDeep = Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new);
gridDeep[1][1] = 99;
int last = grid[1][1]; // 4
Like clone(), the methods Arrays.copyOf() and System.arraycopy() make a shallow copy, as the comparison of array cloning in Java shows.
3.2. Copying a List or Map
ArrayList, HashMap, HashSet and other JDK classes override clone(). The copy constructor of a collection and List.copyOf() do the same job without a cast, and all of them copy the references to the elements, not the elements themselves.
ArrayList<Song> songs = new ArrayList<>(List.of(new Song("Yellow", 10), new Song("Clocks", 3)));
ArrayList<Song> cloned = (ArrayList<Song>) songs.clone(); // unchecked cast
List<Song> copied = new ArrayList<>(songs); // copy constructor
List<Song> readOnly = List.copyOf(songs); // unmodifiable copy
boolean sameInClone = cloned.get(0) == songs.get(0); // true
boolean sameInCopy = copied.get(0) == songs.get(0); // true
boolean sameInReadOnly = readOnly.get(0) == songs.get(0); // true
cloned.add(new Song("Fix You", 5));
int size = songs.size(); // 2 (adding to the copy is safe)
For a deep copy of a collection, we copy every element while we build the new collection. In the next snippet, each Song goes through the Song copy constructor.
List<Song> deep = songs.stream().map(Song::new).toList();
deep.get(0).setPlays(99);
int plays = songs.get(0).getPlays(); // 10
Maps work the same way, so for a deep copy of a HashMap we copy each value while putting the entries into a new HashMap, as we do for an ArrayList clone() and deep copy.
4. Copy Constructors and Static Factory Methods
A copy constructor is a constructor that takes one object of its own class and copies that object’s state. For example, new Song(original) creates a new Song with the same title and plays. A static factory method such as copyOf() does the same job from a static method.
A factory method can have a meaningful name, and it can also return a cached object or a subclass object. Both options are plain Java code, so neither needs a marker interface, a cast or a checked exception, and both work with final fields.
4.1. A Deep Copy Constructor
An “Edit playlist” screen in our music app can work on new Playlist(saved) and write the copy back only when the user clicks Save, so a click on Cancel leaves the saved playlist as it was. Playlist has a copy constructor next to its clone() method, and like a deep clone(), the constructor creates a new list and a new Song for each element.
public Playlist(Playlist other) {
this.name = other.name;
this.songs = new ArrayList<>();
for (Song song : other.songs) {
this.songs.add(new Song(song));
}
}
Playlist byConstructor = new Playlist(original);
byConstructor.getSongs().getFirst().setPlays(42);
int plays = original.getSongs().getFirst().getPlays(); // 10
Album, the class with the final field from section 2.5, uses the same pattern, because a constructor is the one place where Java allows the final field to be set.
private final List<Song> tracks;
public Album(Album other) {
this.title = other.title;
this.tracks = new ArrayList<>();
for (Song song : other.tracks) {
this.tracks.add(new Song(song));
}
}
4.2. Copy Constructors and Inheritance
Copy constructors have one limitation. A constructor always creates an object of its own class, so copying a subclass object through the parent’s constructor loses the subclass. Inheritance makes the problem hard to see when the variable has the parent type. In the next snippet, the variable live has the type Song, but the object is a LiveSong.
public class LiveSong extends Song {
private String venue;
public LiveSong(LiveSong other) {
super(other); // copies title and plays
this.venue = other.venue;
}
}
Song live = new LiveSong("Yellow", 10, "Wembley");
Song byConstructor = new Song(live); // Song[title=Yellow, plays=10] (venue is lost)
Song byClone = live.clone(); // LiveSong[title=Yellow, plays=10, venue=Wembley]
The method clone() keeps the subclass, because Object.clone() creates an object of the real class of the object, not of the type of the variable. Keeping the subclass is the one real advantage of clone().
When the copy must keep the subclass (a polymorphic copy), the common alternative is an overridable instance method such as copy(), which each subclass implements with its own copy constructor.
4.3. Static Factory Method
The copyOf() method of Song creates the copy through the normal constructor instead of Object.clone(), so a factory method needs no instanceof Cloneable check.
public static Song copyOf(Song other) {
return new Song(other.title, other.plays);
}
Song factoryCopy = Song.copyOf(original); // Song[title=Yellow, plays=10]
The JDK uses the same style in List.copyOf(), Map.copyOf() and EnumSet.copyOf().
5. Deep Copy With Serialization, Commons Lang and Jackson
Writing a deep copy by hand gets long when many classes are involved, or when the classes come from a library we cannot change. Two generic approaches, serialization and JSON, work for both cases.
Each one converts the object, and every object it refers to, into another format and back, so the round trip creates new objects at every level. Both approaches are much slower than a copy constructor, because every field is written out and parsed again, so we keep them for occasional copies, not for code that runs very often.
5.1. In-Memory Java Serialization
Java serialization turns an object, including every object it refers to, into bytes with ObjectOutputStream, and ObjectInputStream reads the bytes back into new objects. If we write to a byte array and read from the same array, we get a deep copy, which is called deep cloning using in-memory serialization. Every class involved must implement Serializable, so Playlist and Song both implement the interface.
public static <T extends Serializable> T deepCopy(T object) {
try {
var bytes = new ByteArrayOutputStream();
try (var out = new ObjectOutputStream(bytes)) {
out.writeObject(object);
}
try (var in = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
return (T) in.readObject();
}
} catch (IOException | ClassNotFoundException e) {
throw new IllegalStateException("Deep copy failed", e);
}
}
Playlist viaStreams = DeepCopyUtils.deepCopy(original);
viaStreams.getSongs().getFirst().setPlays(99);
int plays = original.getSongs().getFirst().getPlays(); // 10
Serialization skips a field marked transient, so the copy gets null, 0 or false for every transient field.
5.2. Apache Commons Lang SerializationUtils.clone()
Apache Commons Lang has SerializationUtils.clone(), which does the same work in one call.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.21.0</version>
</dependency>
Playlist viaCommons = SerializationUtils.clone(original);
List<Song> commonsSongs = viaCommons.getSongs(); // [Song[title=Yellow, plays=10]]
boolean sameSong = viaCommons.getSongs().getFirst() == original.getSongs().getFirst(); // false
Every class involved must be Serializable. If one class is not, the call throws a SerializationException at runtime, which wraps a NotSerializableException.
5.3. Jackson
Jackson turns the object into JSON text and reads the text back into new objects. The classes do not need the Serializable interface, but Jackson must be able to create them, so our classes have a package-private no-argument constructor plus getters and setters. The example uses Jackson 3.2.3 (tools.jackson.core:jackson-databind).
JsonMapper mapper = JsonMapper.builder().build();
String json = mapper.writeValueAsString(original);
// {"name":"Road Trip","songs":[{"plays":10,"title":"Yellow"}]}
Playlist viaJson = mapper.readValue(json, Playlist.class);
List<Song> jsonSongs = viaJson.getSongs(); // [Song[title=Yellow, plays=10]]
boolean sameSong = viaJson.getSongs().getFirst() == original.getSongs().getFirst(); // false
Jackson 2 (com.fasterxml.jackson.core) uses new ObjectMapper() with the same two methods. A JSON copy contains only the properties Jackson can see, so fields without a getter, or fields marked @JsonIgnore, are lost in the copy.
6. Records and Immutable Objects Need No Cloning
An immutable object cannot change after it is created. Two parts of a program can safely share one immutable object, so a copy is not needed. String, Integer, LocalDate, List.of() and records with immutable components are all immutable. Records do not implement Cloneable unless we add the interface, and there is no reason to add it.
But a record is only as immutable as its components (the fields listed in the record header). Our Track record has a List component, which the caller who passed the list in can still change later. The compact constructor (the record constructor without a parameter list) stores an unmodifiable copy of the list with List.copyOf(), and a “with” method such as withTitle() returns a changed copy instead of changing the record.
public record Track(String title, List<String> artists) {
public Track {
artists = List.copyOf(artists); // unmodifiable copy of the caller's list
}
public Track withTitle(String newTitle) {
return new Track(newTitle, artists);
}
}
List<String> artists = new ArrayList<>(List.of("Coldplay"));
Track track = new Track("Yellow", artists);
artists.add("Someone else");
List<String> trackArtists = track.artists(); // [Coldplay]
Track live = track.withTitle("Yellow (Live)"); // Track[title=Yellow (Live), artists=[Coldplay]]
boolean added = track.artists().add("X"); // java.lang.UnsupportedOperationException
Normal classes follow a few rules to become immutable, as described in how to make a Java class immutable. The fewer mutable objects a program has, the fewer copies it needs.
7. Why Effective Java Advises Against Cloneable
Joshua Bloch, who designed the Java Collections Framework, covers cloning in Effective Java (3rd edition), Item 13, “Override clone judiciously”. In an interview with Artima, Bloch calls clone “deeply broken”, and his reasons match what the earlier sections showed.
- Cloneable has no clone() method. Instead, the interface changes how a protected method in Object behaves, which is not how interfaces are normally used.
- Object.clone() creates objects without calling a constructor, so checks in the constructor do not run for clones.
- The method clone() returns Object and throws a checked CloneNotSupportedException. Callers avoid the cast and the exception only if every class overrides the method carefully.
- The call super.clone() makes a shallow copy, and the compiler gives no warning when a mutable field is not copied.
- A deep clone() cannot assign final fields, as section 2.5 showed.
- A class that extends a Cloneable class inherits its clone() method, so the subclass must keep that behavior correct, even if it never wanted cloning.
Bloch’s advice is to provide a copy constructor or a copy factory instead, and to keep clone() for arrays. For arrays, clone() is the shortest correct way to copy, and each approach has different limits.
| clone() | Copy constructor / copyOf() | Serialization | Jackson | |
|---|---|---|---|---|
| Needs a marker interface | Cloneable | No | Serializable | No |
| Constructor runs | No | Yes | No (only for records) | Yes, no-arg or creator |
| Works with final fields | Not for deep copies | Yes | Yes | With a creator constructor |
| Keeps subclass type | Yes | No | Yes | Only with type info |
| Deep by default | No | We decide | Yes | Yes |
| Speed | Fast | Fast | Slow | Slow |
| Typical use | Arrays, JDK collections | Our own classes | Library classes that are Serializable | Plain data classes |
To pick an approach, we ask a few questions about the object, in the order of the chart.

The Prototype design pattern creates new objects by copying an existing one, so cloning is the main purpose of the Prototype pattern. The same advice still applies, because a copy method based on a constructor works as well as clone().
8. Object Cloning FAQs
8.1. Why Is clone() Protected in Object?
The Object class makes clone() protected so that only classes that choose to support copying expose it. If a class does not override clone(), other code cannot call clone() on it, and the call fails at compile time.
Object copy = new StringBuilder("x").clone();
ProtectedClone.java:3: error: clone() has protected access in Object
Object copy = new StringBuilder("x").clone();
^
1 error
Overriding clone() as public makes the method callable from other classes.
8.2. Does clone() Call the Constructor?
No. Object.clone() allocates the new object and copies the field values itself, so field initializers and constructor code do not run for the clone.
If a class counts instances or checks arguments in the constructor, it must repeat the counting or the checks in clone(), whereas a copy constructor runs that code anyway.
8.3. Is clone() Faster Than a Copy Constructor?
Not by an amount that matters in most code, because for small objects both create one object and copy a few fields.
Bloch recommends clone() for arrays, because for arrays it is often the fastest way to copy. For other classes, we measure first with a benchmark tool such as JMH and only then choose clone() for speed. Serialization and JSON copies are much slower than both, because they convert every field to bytes or text and back.
8.4. Do We Need to Clone String Fields?
No. String is immutable, so the original and the clone can share the same String object. The same is true for wrapper types such as Integer, for LocalDate and for other immutable classes.
8.5. How Do We Deep Copy an Object Without Cloneable?
We write a copy constructor or a copyOf() method that copies every mutable field (section 4). For classes we cannot change, SerializationUtils.clone() works when every object involved is Serializable, and Jackson works for classes with getters and setters, or with creator constructors (section 5).
9. Conclusion
To clone an object in Java, we can implement Cloneable and override clone() with a public method that calls super.clone(). But super.clone() only makes a shallow copy, so mutable fields such as lists and arrays must be copied by hand, and final fields block that step.
For our own classes, a copy constructor or a static copyOf() method is clearer and works with final fields. Arrays and JDK collections already have a shallow clone() or a copy constructor. Serialization and Jackson can deep copy an object and everything it refers to, at a higher cost. Records and other immutable objects need no copy at all.
10. References
- Object.clone() JavaDoc (Java 25))
- Cloneable JavaDoc and CloneNotSupportedException JavaDoc
- Java Language Specification, Arrays (chapter 10)
- Apache Commons Lang SerializationUtils
- Effective Java, 3rd edition
Happy Learning !!
Well written! I am was looking for it very long. Thank for the explanation.
You have missed declaring PointOne copyPoint(PointOne point) as static.
Good catch. Thanks for pointing out.
Good catch. Thanks for pointing it out.
You are welcome, Javin. Appreciate you took the time to share your thoughts.
I have a question regarding the copy constructor, I did exactly as the one you presented and i got an error line when I passed the Integer values as arguments in the constructor after creating the objects of classes PointOne and PointTwo. This line of code
“PointOne one = new PointOne(1,2);
PointTwo two = new PointTwo(1,2,3);”.
Yes, It’s obvious, We will get compile time error while copy the above code as it is.
You have to add two more constructor in the code-
public PointOne(int x, int y){ //For PointOne class constructor
this.x = x;
this.y=y;
}
public PointTwo(int x, int y, int z){ // For PointTwo class constructor
super.x = x;
super.y = y;
this.z=z;
}
So impressive. I have a question , what if Department class is also having another reference of another object and so on.. Do we need to take care manually for this chain of objects to get Deep cloned object, or any other approach we have other than serialization?
thank you in advance.
Ideally, it should be done for all objects in the chain. But if it is not possible due to some reason, consider serializing Java object to JSON string and store in database.
can anyone explain this to me :
cloned.getDepartment().setName(“Finance”);
getDepartment() method belongs to which class and setName() method belongs to which class since there are two classes i.e., Employee and Department. Also, can anyone show me the Structure of these methods and how to pass on the argument “finance” to the setName() method
Employee.java
public class Employee implements Cloneable { private int empoyeeId; private String employeeName; private Department department; public Employee(int id, String name, Department dept) { this.empoyeeId = id; this.employeeName = name; this.department = dept; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } public int getEmpoyeeId() { return empoyeeId; } public void setEmpoyeeId(int empoyeeId) { this.empoyeeId = empoyeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } }Department.java
package com.example.howtodoinjava.dozer.simple; public class Department { private int id; private String name; public Department(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }Thanks for the knowledge.
***** Very nice post to understand cloning
Thanks.
Excellent!
Tks!
Good article, I always I’ve been looking for clone. In my opinion “SerializationUtils” of apache is the cleanest way to clone simple java object.
A well explained tutorial on object cloning… Thanks..
what are the uses of cloning in real time??
A common use is immutable objects.
If an object is immutable, why would you clone it? You’d only need another immutable object when you change some property of the original, in which case it would be a new instance with some changes and not related at all to the original object.
Absolutely right. BUT an immutable object may have mutable references e.g. date objects. To prevent modifying the state of such objects, you will need to clone these mutable “field references” and return via getYYY() methods.
Great Post. Keep posting.
Nice post! Keep sharing more such stuffs !
Very nice tutorial. Indeed I have got one query. In the TestCloning example above, where we are cloning the objects of Employee class to get the original object, the references got copied, not the object if this is the case, then why does original != cloned returns true?because == method returns true if both the references refers to the same object..?
@isha
clone() returns new instance of class (new object). In the example it returns new instance of Employee. Cloned Employee will have different memory address than the original Employee, thereofre original!=cloned. But: original.department == cloned.department is true.
Nice Post
Very good tutorial..Made me to understand the cloning stuff with such ease…Thanks you very much for your efforts…
You are excellent
copyPoint is not static in your example for “static factory methods”. Do you see an issue with keeping it the way you have it?
Static method way:
PointOne one = new PointOne(1,2);
PointOne two = PointOne.copyPoint(one);
Your way:
PointOne one = new PointOne(1,2);
PointOne two = one.copyPoint(one);
I like your way better than the static method because you can define the copyPoint method in an interface. Your thoughts?
Also, with your way you do not need to pass the object being copied. just change the return type as follows. This just seems cleaner to me and you can define in interfaces. Is there a disadvantage over having the method static?
public PointOne copyPoint() throws CloneNotSupportedException
{
…
return new PointOne(thiS.x, this.y);
}
I do not see any disadvantage. It’s much cleaner.
If there’s a subclass, say, ColoredPointOne, then this will (by inheritance) be Cloneable too, and have a public clone method. This needs to be overridden to create a proper ColoredPointOne clone. If PointOne.clone returns a PointOne object, then ColoredPointOne can’t reuse it by calling super.clone. If you use super.clone() instead of new PointOne, then Object.clone will create the object for you, and it will be of type ColoredPointOne if that is the runtime type.
Why are you using my user id and email address to comment? I just received an update in my email after someone commented on your comment.
Guys, please use only your email ids for commenting and do not trouble anybody un-necessary.
Hi Lokesh,
This new look to your blog is making very difficult to search topics under one category.
Pls suggest way to browse thru all core java topics as you had in the earlier look. there is no search button too on this home page that can take me to the right location.
I also feel so. Bringing back old again.
Hi Lokesh,
I have a doubt that If we call clone() method on any object, Constructor will be called for that or not?
Thanks,
H Singh
Read the “Best Practices” section #2.
you are just overriding clone() method. to override any method constructor is not required.
How can we clone an Object of unknown type? What if that object’s class doesn’t implement Cloneable or Serializable?
I guess, then we are left with reflexion i.e. to iterate over all fields and copy in new object.
You are excellent Lokesh.
Thanks for such a great information. The content is very informative.
Hi Lokesh,
Thanks for the information. nice post.
I am not really sure what problem do you see with following lines you mentioned.
PointOne clone1 = new PointOne(one);
PointOne clone2 = new PointOne(two);
In the second line, even though object ‘two’ is passed the object being created is PointOne. I don’t see any problem with it.
Thanks
Ramesh
Clone means that both objects must have same state. In above code, they do not have because point b has one extra field, which is lost in second statement.
THANKS. Very helpful.
Thanks for sharing .. Well explained.
Correct me if I am wrong , but I would like to make some observations on the paragraph “Deep cloning”.
First : I think you should declare class Department as implementing Cloneable interface , since you invoke
method clone in class Employee row 5.
Second : I think you should change the access modifier of method clone from class Department , from “protected” to “public” , in order to make it accessible in the same place mentioned before.
Last : I suppose it would be worth mentioning that the two String fields involved in cloning class Employee (one inside it and one inside the underlying Department object) can be left uncloned because String class is immutable.
Hey buddy, thanks for invaluable inputs.
First: This is definitely Typo error and Department must implement Cloneable interface.
Two: No need to make clone() method public. We are overriding it from object class, and there it is declared protected. Remember, overriden methods can not widen the scope.
Last: You are correct. Actually, all java classes have 3 types of attributes : primitives, mutable references and immutable references. There is no need to handle primitives and immutable references, but mutable references must be explicitly cloned OR copied.
I think you can widen the scope but you cannot reduce the scope
It’s opposite
But i searched the web and many sources say that The overridden method can widen the accessibility but not narrow it, i.e. if it is private in the base class, the child class can make it public but not vice versa.
Yes, you are correct. Forgive me for creating confusion. I got confused with scopes of exception thrown (you cannot widen it). Thanks for your input.
So what is the output for point 2? The protected clone method in Department class cannot be called in Employee class due to access restriction:
cloned.setDepartment((Department) cloned.getDepartment.clone());
Protected has access only within the same class or class extending the original and here there is no such relation between Employee and Department class.
Not clear please elaborate.
We can access the protected methods in same package. In this example, Employee and Department are in the same package so it can be accessed. The important thing is that we are call the clone() method defined in the Department class. If we do not override the clone() method in Department then method will be invoked from the Object class, and that is not allowed due to access restriction.
for point Second:
The method name can be any thing. e.g. it can be myClone like below. Important point is you need to call “super.clone()” as it is.
public Object myClone() throws CloneNotSupportedException {
return super.clone();
}
now your department object will be called like
Department clonedDeptt = existingDeptt.myClone();
Thanks
Manish
If somebody extend your class and implement his method as “wowClone(){…}”. Would he call your super.myClone() or super.clone()… Lesson: Don’t make things complicated. If you really want to do such thing, use static method to create new instances.
Thats correct Lokesh, it was to demonstrate and to clear the confusions among people who thinks that we are overriding clone method that is written in Object class.
Thanks,
Manish
So you mean to say… the Department Class does not over ride clone method, it is just a syntax? Is it correct??