Copy constructor and factory method in Java
This post will discuss how to copy objects in Java using a copy constructor. We will also cover the Factory method approach that does the same.
Copy Constructor
A copy constructor is a special constructor for creating a new object as a copy of an existing object. It defines the actions performed by the compiler when copying class objects. It is a very good practice always to have a copy constructor defined in the class.
It has just one argument that is usually a reference to an object of the same type as is being constructed. In other words, it accepts a parameter that is just another instance of the same class.
Any copy constructor implementation usually uses an assignment operator = for primitive & immutable fields and a new operator for mutable fields & objects for copying objects in Java. This will result in a Deep Copy.
Copy constructors are the preferred way of copying objects in Java, as opposed to clone() Method. There are several advantages of using copy constructor over the clone() method:
- It is much more simpler to use the copy constructor on a complex object with many fields.
- Default implementation of
Object.clone()returns a shallow copy. Copy constructors can easily return deep copies for non-complex objects. - Copy constructors don’t force us to implement
CloneableorSerializableinterface. Object.clone()throwsCloneNotSupportedExceptionwhen class fails to implementCloneableinterface. Copy constructors don’t throw any such exception.Object.clone()returns anObjectand typecasting is needed to assign the returned Object reference to a reference to an object. No such typecasting is needed for Copy constructors.- Copy constructors gives us complete control over object initialization, unlike default implementation of
Object.clone(). We can have mix of deep and shallow copies for different fields in the class. - The
Object.clone()method will result in a compilation error if we try assign a value to a final field on the object received from the superclass. Copy constructors, on the other hand, will allow us to assign a value to a final field just once.
The following program demonstrates it:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
import java.util.Arrays; import java.util.HashSet; import java.util.Set; class Student { private String name; private int age; private Set<String> subjects; public Student(String name, int age, Set<String> subjects) { this.name = name; this.age = age; this.subjects = subjects; } // Copy constructor public Student(Student student) { this.name = student.name; this.age = student.age; // shallow copy // this.subjects = student.subjects; // deep copy – create a new instance of `HashSet` this.subjects = new HashSet<>(student.subjects); } @Override public String toString() { return Arrays.asList(name, String.valueOf(age), subjects.toString()).toString(); } public Set<String> getSubjects() { return subjects; } } // Copying objects in Java using the copy constructor class Main { public static void main(String[] args) { Student student = new Student("Jon Snow", 22, new HashSet<String>( Arrays.asList("Maths", "Science", "English")) ); // calling copy constructor Student s = new Student(student); System.out.println("Using Copy Constructor: " + s.toString()); // any change made to the s's map will not reflect on the student's map s.getSubjects().add("History"); System.out.println(student.getSubjects()); } } |
Output:
Using Copy Constructor: [Jon Snow, 22, [Maths, English, Science]]
[Maths, English, Science]
Copy Factory
We can also use the static copy factory method to essentially do the same thing as the copy constructor method. This approach is shown below:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
import java.util.Arrays; import java.util.HashSet; import java.util.Set; class Student { private String name; private int age; private Set<String> subjects; public Student(String name, int age, Set<String> subjects) { this.name = name; this.age = age; this.subjects = subjects; } // Copy constructor public Student(Student student) { this.name = student.name; this.age = student.age; this.subjects = new HashSet<>(student.subjects); // deep copy } // Copy factory public static Student newInstance(Student student) { return new Student(student); } @Override public String toString() { return Arrays.asList(name, String.valueOf(age), subjects.toString()).toString(); } public Set<String> getSubjects() { return subjects; } } // Copying objects in Java using copy factory class Main { public static void main(String[] args) { Student student = new Student("Jon Snow", 22, new HashSet<String>( Arrays.asList("Maths", "Science", "English")) ); // using copy factory Student s = Student.newInstance(student); System.out.println("using copy factory: " + s.toString()); // any change made to the s's map will not reflect on the student's map s.getSubjects().add("History"); System.out.println(student.getSubjects()); } } |
That’s all about the copy constructor and factory method in Java.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)