-2.9 C
New York
Monday, January 15, 2024

The right way to copy objects in Java: Shallow copy and deep copy


Copying objects is a standard operation in enterprise initiatives. When copying an object, we should be sure that we find yourself with a brand new occasion that holds the values we wish.

Area objects are normally complicated. Making a replica with the foundation object and composed objects can be not trivial.

Let’s discover the best methods to repeat an object utilizing shallow and deep copy strategies.

Object references

To appropriately carry out a shallow or deep object copy, we should first know what to not do. Understanding object references is crucial for utilizing shallow and deep copy strategies.

When making a replica of an object, you will need to keep away from utilizing the identical object reference. It is a simple mistake, as this instance reveals. To start out, here is the Product object we’ll use in our examples:


public class Product {

  personal String title;
  personal double worth;

  public Product(String title, double worth) {
    this.title = title;
    this.worth = worth;
  }

  public String getName() { return title; }
  public double getPrice() { return worth; }

  public void setName(String title) { this.title = title; }
  public void setPrice(double worth) { this.worth = worth; }

}

Now, let’s create and assign a Product object reference to a different variable. It appears to be a replica, however actually, it is the identical object:


public static void primary(String[] args) {
    Product product = new Product("Macbook Professional", 3000);
    Product copyOfProduct = product;

    product.title = "Alienware";
    System.out.println(product.title);
    System.out.println(copyOfProduct.title);
  }

The output of this code is


Alienware
Alienware

Discover within the code above that we assign the item’s worth to a distinct native variable, however this variable factors to the identical object reference. If we alter the product or copyOfProduct objects, the end result will likely be a change to the unique Product object.

That is as a result of each time we create an object in Java, an object reference is created in Java’s reminiscence heap. This lets us modify objects utilizing their reference variables.

Shallow copy

The shallow copy method permits us to repeat easy object values to a brand new object with out together with the interior object values. For example, here is how you can use the shallow copy method to repeat the Product object with out utilizing its object reference:


// Omitted the Product object

public class ShallowCopyPassingValues {
  public static void primary(String[] args) {
    Product product = new Product("Macbook Professional", 3000);
    Product copyOfProduct = new Product(product.getName(), product.getPrice());

    product.setName("Alienware");
    System.out.println(product.getName());
    System.out.println(copyOfProduct.getName());
  }
}

The output is


Alienware
Macbook Professional

Discover on this code that after we go the values from one object to the opposite, two completely different objects are created within the reminiscence heap. Once we change one of many values within the new object, the values will stay the identical within the authentic object. This proves the objects are completely different and we have efficiently executed the shallow copy.

Observe: The Builder design sample is one other method to carry out the identical motion.

Shallow copy with Cloneable

Since Java 7, we have had the Cloneable interface in Java. This interface offers one other method to copy objects. As a substitute of implementing the copy logic manually, as we simply did, we will implement the Cloneable interface after which implement the clone() technique. Utilizing Cloneable and the clone() technique robotically ends in a shallow copy.

I do not like this system as a result of it throws a checked exception, and we’ve got to manually forged a category kind, which makes the code verbose. However utilizing Cloneable would possibly simplify the code if we’ve got an enormous area object with many attributes.

Here is what occurs if we implement the Cloneable interface in a website object after which override the clone() technique:


public class Product implements Cloneable {

  // Omitted attributes, strategies and constructor

  @Override
  protected Object clone() throws CloneNotSupportedException {
    return tremendous.clone();
  }

}

Now, here is the copy technique in motion once more:


public class ShallowCopyWithCopyMethod {
  public static void primary(String[] args) throws CloneNotSupportedException {
    Product product = new Product("Macbook Professional", 3000);
    Product copyOfProduct = (Product) product.clone();

    product.setName("Alienware");
    System.out.println(product.getName());
    System.out.println(copyOfProduct.getName());
  }
}

As you may see, the copy technique works completely for making a shallow copy of an object. Utilizing it implies that we need not copy each attribute manually.

Deep copy

The deep copy method is the power to repeat a composed object’s values to a different new object. If the Product object accommodates the Class object, for instance, it is anticipated that each one the values from each objects can be copied to a brand new object.

What occurs if the Product object has a composed object? Will the shallow copy method work? Let’s examine what occurs if we attempt to use solely the copy() technique.

To start out, we compose the Product class with the Order object:


public class Product implements Cloneable {
  
  // Omitted different attributes, constructor, getters and setters
  personal Class class;

  public Class getCategory() { return class; }

}

Now, let’s do the identical factor utilizing the tremendous.clone() technique:


public class TryDeepCopyWithClone {

  public static void primary(String[] args) throws CloneNotSupportedException {
    Class class = new Class("Laptop computer", "Transportable computer systems");
    Product product = new Product("Macbook Professional", 3000, class);
    Product copyOfProduct = (Product) product.clone();

    Class copiedCategory = copyOfProduct.getCategory();

    System.out.println(copiedCategory.getName());
  }
}

The output is


Laptop computer

Discover that despite the fact that the output is “Laptop computer,” the deep copy operation didn’t occur. What occurred as an alternative is that we’ve got the identical Class object reference. Here is the proof:


public class TryDeepCopyWithClone {
  public static void primary(String[] args) throws CloneNotSupportedException {
    // Similar code as the instance above
    
    copiedCategory.setName("Cellphone");
    System.out.println(copiedCategory.getName());
    System.out.println(class.getName());
  }
}

Output:


Laptop computer
Cellphone
Cellphone

Discover on this code {that a} copy was not made after we modified the Class object. As a substitute, there was solely an object task to a distinct variable. Subsequently, we’ll change the item we created within the reminiscence heap every time we alter the reference variable.

Deep copy with the clone() technique

Now we all know that the clone() technique will not work for a deep copy if we’ve got a easy override. Let’s examine how we will make it work.

First, we implement Cloneable within the Class class:


public class Class implements Cloneable {

  // Omitted attributes, constructor, getters and setters

  @Override
  protected Object clone() throws CloneNotSupportedException {
    return tremendous.clone();
  }
}

Now, we’ve got to alter the implementation of the Product clone technique additionally to clone the Class object:


public class ProductWithDeepCopy implements Cloneable {

  // Omitted attributes, constructor, getters and setters

  @Override
  protected Object clone() throws CloneNotSupportedException {
    this.class = (Class) class.clone();
    return tremendous.clone();
  }
}

If we attempt to carry out the deep copy with the identical code instance as above, we are going to get an actual copy of the item values into a brand new object, as proven right here:


public class TryDeepCopyWithClone {

  public static void primary(String[] args) throws CloneNotSupportedException {
    Class class = new Class("Laptop computer", "Transportable computer systems");
    Product product = new Product("Macbook Professional", 3000, class);
    Product copyOfProduct = (Product) product.clone();

    Class copiedCategory = copyOfProduct.getCategory();

    System.out.println(copiedCategory.getName());
    copiedCategory.setName("Cellphone");
    System.out.println(copiedCategory.getName());
    System.out.println(class.getName());
  }
}

The output is


Laptop computer
Cellphone
Laptop computer

Since we manually copied the class technique within the copy() technique of Product, it lastly works. We’ll get a replica from Product and Class utilizing the copy() technique from Product.

This code proves that the deep copy labored. The values of the unique and copied objects are completely different. Subsequently, it is not the identical occasion; it is a copied object.

Shallow copy with serialization

it’s typically essential to serialize an object to remodel it into bytes and go it by a community. This operation might be harmful as a result of if not validated appropriately, the serialized object could be exploited. The safety of Java serialization is out of the scope of this text, however let’s examine the way it works with code.

We’ll use the identical class from the instance above however this time, we’ll implement the Serializable interface:


public class Product implements Serializable, Cloneable {
   // Omitted attributes, constructor, getters, setters and clone technique
}

Discover that solely the Product will likely be serialized since solely the Product implements Serializable. The Class object will not be serialized. Here is an instance:


public class ShallowCopySerializable {

  public static void primary(String[] args) {
      attempt {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);

        Product product = new Product("Macbook Professional", 3000);
        out.writeObject(product);
        out.flush();
        out.shut();

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bis);
        Product clonedProduct = (Product) in.readObject();
        in.shut();

        System.out.println(clonedProduct.getName());
        Class clonedCategory = clonedProduct.getCategory();
        System.out.println(clonedCategory);
      } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
      }
  }
}

The output is


Macbook Professional
null

Now, if we tried to populate the Class object into the Product object, the java.io.NotSerializableException can be thrown. That is as a result of the Class object doesn’t implement Serializable.

Deep copy with serialization

Now,  let’s examine what occurs if we use the identical code as above however add the next within the Class class:


public class Class implements Serializable, Cloneable {
  // Omitted attributes, constructor, getters, setters and clone technique

  // Including toString for an excellent Object description
  @Override
  public String toString() {
    return "Class{" + "title="" + title + "'' + ", description='" + description + ''' + '}';
  }
}

By working the identical code because the shallow serializable copy code, we’ll get the end result from Class, as effectively, and the output must be the next:


Macbook Professional
Class{title="Laptop computer", description='Transportable computer systems'}

Observe: To additional discover Java serialization, check out the Java code problem right here.

Conclusion

Generally the shallow copy method is all you want to clone an object superficially. However whenever you need to copy each the item and its inside objects, you could implement a deep copy manually. Listed here are the important thing takeaways from these vital strategies.

What to recollect about shallow copy

  • A shallow copy creates a brand new object however shares the references of the interior objects with the unique object.
  • The copied and authentic objects discuss with the identical objects in reminiscence.
  • Modifications made to the interior objects by one reference will likely be mirrored in each the copied and authentic objects.
  • Shallow copy is an easy and environment friendly course of.
  • Java offers a default implementation of shallow copy by the clone() technique.

What to recollect about deep copy

  • A deep copy creates a brand new object and likewise creates new copies of its inside objects.
  • The copied and authentic objects have unbiased copies of the interior objects.
  • Modifications made to the interior objects by one reference is not going to have an effect on the opposite.
  • Deep copy is a extra complicated course of, particularly when coping with object graphs or nested references.
  • Deep copy have to be carried out explicitly, both manually or utilizing libraries or frameworks.

This story, “The right way to copy objects in Java: Shallow copy and deep copy” was initially revealed by

JavaWorld.

Copyright © 2024 IDG Communications, Inc.



Supply hyperlink

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles