Copy Constructor in Java with Examples

Get Job-ready: Java Course with 45+ Real-time Projects! - Learn Java

In C++, there is a concept of a copy constructor. Similarly, Java also supports Copy constructors, but the difference is that in C++, the copy constructor is created by default, while in Java, we have to create the copy constructor on our own. In this article, we will see how to create a copy constructor and why it is necessary in our programs.

What are Constructors in Java?

Before learning about copy constructors, we need to understand the concept of constructors. Constructors are special methods that have the same name as the class. Using constructors, we can initialize global variables. Constructors do not have any return type. They are called automatically when an object is declared for that class. Constructors occupy space according to the variables present in them.

Types of Java Constructors:

1. Default Constructor in Java

Constructors that do not have a parameter list are known as a default constructor.

Example of Default Constructor in Java:

package com.DataFlair.CopyConstructor;
public class DefaultConstructor
{ 
    DefaultConstructor()
    {
        System.out.println("Object Created, so Constructor Called");
    }    
    public static void main(String args[])
    {   
        DefaultConstructor d=new DefaultConstructor(); 
    }
}

The output of the above code:

Object Created, so Constructor Called

2. Parameterized Constructor in Java

These are the Constructors which have a parameter list.

Example of Parameterized Constructor in Java:

package com.DataFlair.CopyConstructor;
public class ParameterConstructor
{
    int id;  
    String name;
    ParameterConstructor(int i,String n){  
    id = i;  
    name = n;  
    }  
    void display()
    {
        System.out.println(id+" "+name);
    }
    public static void main(String args[]){   
    ParameterConstructor P = new ParameterConstructor(1,"Arka");
    P.display();  
   }  
}  

The output of the above Code:

1 Arka

Other than these two Constructors, Java also supports copy constructors. We will discuss it in detail now.

What is a Copy Constructor in Java?

As the name suggests, the copy constructor is used to create a copy of a previously existing object present in the class. It is a special type of constructor that returns a duplicate copy of another object.
In the C language, the copy constructor is declared automatically, but in Java, we have to create the method separately.

Why is it required to use the Java Copy Constructor?

The main purpose of a copy constructor is to create a copy of an object. This helps in the reusability of code. Sometimes, when there is a need to make changes to the attributes of the object without affecting the original object, we create a copy of the object. For such scenarios, a copy constructor is essential.

Creating a Copy Constructor in Java

The steps to create a copy constructor are as follows:

Step 1: We have to create a constructor that takes an object as a parameter. Make sure that the object belongs to the same class.

public class Interns  
{   
private int ID;   
private String name;    
public Interns(Interns interns)//copy constructor  
{   
//getters  
}   
}  

Step 2: Using getters, copy each variable of the copied object to the new instances.

public class Interns  
{   
private int ID;   
private String name;    
public Interns(Interns interns)//copy constructor  
{   
this.ID=interns.ID;//getters  
this.name=interns.name;//getters
}   
}

How to Copy Mutable Type data in Java?

To copy mutable type data, we have to create a deep copy instead of a shallow copy, which we did in the previous example.

Let us understand this with a code:

Code to understand Mutable data with copy constructor:

public class Interns
{
        private int ID;
        private String name;
        private Date InternDate;//Mutable Data

        public Interns( Interns interns )
        {
                this.roll = interns.id;
                this.name = interns.name;
                this.InternDate = new Date(interns.InternDate.getTime());//Deep Copy
        }
}

Code to explain the working of the copy constructor in Java:

package com.DataFlair.CopyConstructor;
public class Interns
{  
    private int ID;   
    private String Name; 
    Interns(int id, String name)//parameterized constructor
    {
        ID=id;
        Name=name;
    }
    Interns(Interns interns)//copy constructor  
    {   
        System.out.println("The Copy Constructor Starts here");
        ID=interns.ID;//getters  
        Name=interns.Name;//getters
    }   
    int showID()
    {
        return ID;
    }
    String showName()
    {
        return Name;
    }
    public static void main(String[] args)
    {
        Interns I=new Interns(1,"Arka");
        System.out.println("ID of Intern: "+ I.showID()+ " Name of Intern:"+ I.showName());
        Interns IC=new Interns(I);
        System.out.println("ID of Intern: "+ I.showID()+ " Name of Intern:"+ I.showName());
    }
}

The Output of the above Program:

ID of Intern: 1 Name of Intern:Arka
The Copy Constructor Starts here
ID of Intern: 1 Name of Intern:Arka

Advantages of Using Copy Constructor in Java

  • The copy constructor can be used to change the state of a variable from final to normal.
  • In the copy constructor, there is no need for Type Casting.
  • We can change the copied object without harming the original object.
  • It reduces the size of the code.
  • It enhances code reusability.
  • Copy Constructor is easier when there are several fields in it.

To understand the advantage of a copy constructor, let us try to copy an object without using a copy constructor.

Code for creating a copy of an object without using the copy constructor:

package com.DataFlair.CopyConstructor;
public class Intern
{
     private int ID;
     private String name;
  Intern(int id, String Name)
  { 
    ID = id;
    name= Name;
  }
  
  Intern()
  {  
  }
  int printID()
  {
    return ID;
  }
  String printName()
  {
    return name;
  }
  public static void main(String[ ] args)
  {
    Intern I1 = new Intern(1, "Arka");
    System.out.println("ID of Intern: "+ I1.printID());
    System.out.println("Name of Intern: "+ I1.printName());

    Intern I2 = new Intern();
    I2.ID= I1.ID;
    I2.name= I1.name;

    System.out.println("Copied ID of Intern: "+ I2.printID());
    System.out.println("Copied Name of Intern: "+ I2.printName());
}
}

The output of the above code:

ID of Intern: 1
Name of Intern: Arka
Copied ID of Intern: 1
Copied Name of Intern: Arka

So, we can clearly see that the size of the code increased considerably for only 2 variables. Now, imagine if there are 50 such variables, how hard it will be to copy each variable separately. So, we can see why a copy constructor is an important concept to write optimal code.

Best Practices for Java Copy Constructors

When crafting copy constructors, here are some valuable guidelines to consider:

  • Deep vs. Shallow Copying: Be mindful of whether you require a deep copy or a shallow copy. A deep copy replicates the entire object structure, including mutable references. A shallow copy duplicates the object’s state, but references to mutable objects point to the same underlying instances in memory. Utilise deep copying when essential to ensure modifications to the copy don’t affect the original object.
  • Final Fields: Copy constructors allow modification of final fields during copying. This can be useful in specific scenarios, but exercise caution to avoid unintended consequences.
  • Using the shallow copy to clone the object will affect the newly created object if changes are made to the previous object. But if using the deep copy of the constructor, any changes made to the original object will not be reflected in the copied object.

Difference Between Java Copy Constructor and Clone() Method:

Clone() is also a method using which we can use to create a duplicate copy of a pre-existing object. But using a clone method is more difficult compared to a copy constructor, due to the following reasons:

1. The clone method may throw an exception if the cloneable is not imported properly. Handling an exception is an extra task. While the Copy Constructor does not throw any such exceptions.

2. Using Clone(), we cannot assign values to variables that are declared final. As we all know by now, the copy constructor allows us to change the value of final variables.

3. In the Clone() method, typecasting is required, while in the copy constructor, typecasting is not required.

Inheritance Issues in Java Copy Constructor:

One very big disadvantage of the copy constructor is that the subclasses of the parent class that contain the copy constructor cannot access the copy constructor. The program will give a casting error when we try to compile it.

Code explaining the Problem with inheritance and copy constructor:

package com.DataFlair.CopyConstructor;
import java.util.List;

public class TechWriter extends Interns
{
private List<Interns> Articles;
public TechWriter(TechWriter techwriter)
{
            super(techwriter.ID, techwriter.name);
            this.Articles = Articles.stream().collect(Collectors.toList());
}
}

The above code will give an error, as the compiler will not be able to recognize the variables ID and name. To fix this we have to typecast the variable with the subclass.

For Example:

Interns clone = new TechWriter((Techwriter)interns);

We can avoid typecasting by adding a new inherited method to both classes.

Code explaining how to avoid type casting in case of inherited copy constructor:

public class Interns
{
public Interns copy()
{
            return new Interns(this);
      }
}
 
public class Techwriter extends Interns
{
@Override
      public Interns copy() 
{
            return new Techwriter(this);
      }
}

Quiz on Java Copy Constructor

Common Use Cases for Copy Constructors in Java

Copy constructors offer a versatile mechanism for object duplication in various situations. Here are a few examples:

  • Passing Objects to Methods: When passing objects to methods, you might want to create a copy to prevent unintended alterations to the original object. The copy constructor facilitates this by generating a duplicate that can be safely modified within the method.
  • Defensive Copying: In scenarios where you receive external data that may be corrupt or tampered with, creating a copy using the copy constructor allows you to work with a safe replica, protecting your core application logic.
  • State Management: Copy constructors can be instrumental in implementing the memento pattern, a software design pattern that facilitates reverting an object to a previous state. By creating a copy using the copy constructor, you can preserve a specific object state for potential restoration.

Conclusion

We conclude that Constructors in Java are an important aspect of programming. When it comes to initialising the object state or modifying the object’s behaviour, the work is done by the constructor.

Java constructors are one of the most important concepts when it comes to writing effective code. In this article, we saw how to declare a copy constructor manually in Java. We also saw the importance, advantages, and disadvantages of using copy constructors.

Did you know we work 24x7 to provide you best tutorials
Please encourage us - write a review on Google

courses

DataFlair Team

DataFlair Team is a group of passionate educators and industry experts dedicated to providing high-quality online learning resources on programming, Java, Python, C++, DSA, AI, ML, data Science, Android, Flutter, MERN, Web Development, and technology. With years of experience in the field, the team aims to simplify complex topics and help learners advance their careers. At DataFlair, we believe in empowering students and professionals with the knowledge and skills needed to thrive in today’s fast-paced tech industry. Follow us for Free courses, expert insights, tutorials, and practical tips to boost your learning journey.

Leave a Reply

Your email address will not be published. Required fields are marked *