Redcoatwright
Redcoatwright

Reputation: 157

First time creating a copy method

I'm attempting to create a copy method, but what I have seems too simple and I think it's essentially doing nothing.

public Validation copy(Validation newValidation){return newValidation;}

so if implemented like so:

Validation x = new Validation(); 
Validation y = x.copy(x);

And then make sure that y has all the methods/variables of x and that when working with the variables in y, I don't affect the variables in x. I have a feeling what I want is a "deep copy" method and I found a post about it here: Creating a deep copy method, Java but that person has no argument for their method so I don't know how it is actually copying.

Upvotes: 2

Views: 2987

Answers (2)

Merve Sahin
Merve Sahin

Reputation: 1048

The Java api has a Cloneable Interface.Object has a clone method that can only be accessed when it's overridden in the subclass, that also implements the Cloneable interface. Your method does not really create a copy, since the "copy" points to the original instance.

Let's say I make a copy of Validation :

Validation v = new Validation();
v.setId(1);
Validation valid = v.copy(v);
valid.setId(2);

Now the id in v will change as well, because valid points to v.

But the clone-Method makes a deep-copy. Here is a small example :

public class Product {

private int id;
private String 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;
}

@Override
public String toString() {
    return "Product{" + "id=" + id + ", name=" + name + '}';
}

@Override
protected Object clone() throws CloneNotSupportedException {
    Product p = new Product();
    p.setId(id);
    p.setName(name);
    return p;
}   

}

public static void main(String[] args) {
    Product p = new Product();
    try {
        Product clone = (Product) p.clone();
        System.out.println(clone.toString());
    } catch (CloneNotSupportedException ex) {
        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
    }
}

Upvotes: 0

Andrew
Andrew

Reputation: 49656

Yes, it does nothing except returning the same reference that has been passed.

Probably, you are looking for the Object#clone()* method:

public Validation copy(Validation newValidation) {
    return newValidation.clone();
}

In 95% cases, that is the most appropriate and proper solution for different types of tasks. You should not reinvent the wheel if there isn't a need of it.

As the Java documentation says:

... this method performs a "shallow copy" of this object, not a "deep copy" operation.

... it may be necessary to modify one or more fields of the object returned by super.clone before returning it.

Validation y = x.copy(x);

You shouldn't pass an x to a copy method because when you are calling this method on an x instance, inside the class you have an access to this which, in this case, represents your x.

Validation y = x.clone();

For a "shallow copy" the preceding example is good, but for a "deep copy" you need to override a default Object#clone() behaviour:

class A implements Cloneable {
    
    public @Override A clone() throws CloneNotSupportedException {
        return (A)super.clone(); // or or another implementation
    }
    
}

class Validation implements Cloneable {

    // an example of a reference-type field
    private A a; // with a setter

    public @Override Validation clone() throws CloneNotSupportedException {
        Validation newClone = new Validation();

        // note that the `A` class has to implement the `Cloneable`
        // and override the `clone` method making it `public`
        newClone.setA(this.a.clone());

        return newClone;
    }
    
}

*Don't forget to implement the Cloneable interface to allow cloning.

To read: Effective Java, Item 11: Override clone judiciously.

Upvotes: 1

Related Questions