2

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.

Community
  • 1
  • 1
Redcoatwright
  • 129
  • 1
  • 5
  • 17
  • Whether you need a deep copy or not, It all depends upon the code inside Vlidation class, can you provide your Validation code ? – Vasu Oct 29 '16 at 20:14
  • The example in the link creates a copy of the current object (`this`). – infiniteRefactor Oct 29 '16 at 20:23
  • Possible duplicate of [Clone() vs Copy constructor- which is recommended in java](http://stackoverflow.com/q/2427883/5221149). – Andreas Oct 30 '16 at 13:44

2 Answers2

1

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.

Community
  • 1
  • 1
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • Oh okay, so this will produce a duplicate object but whose variables have different references than the first object? – Redcoatwright Oct 30 '16 at 01:21
  • @Redcoatwright, No, instance field references will be the same as in the origin object – Andrew Tobilko Oct 30 '16 at 11:05
  • Josh Bloch says that [clone is broken](http://www.artima.com/intv/bloch13.html), and that you should [use a copy-constructor instead](http://stackoverflow.com/q/2427883/5221149). – Andreas Oct 30 '16 at 13:41
  • @Andreas, should we use copy-constructors hierarchically for "deep copying"? – Andrew Tobilko Oct 30 '16 at 13:46
  • For a deep copy, you should use whatever method is available for copying of the modifiable nested objects that are part of the object composition. – Andreas Oct 30 '16 at 15:16
0

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);
    }
}
Merve Sahin
  • 1,008
  • 2
  • 14
  • 26
  • Sorry, that might be a bit over my head. What does the "throws" do? – Redcoatwright Oct 30 '16 at 01:20
  • 1
    There is a bad example, do you realise that a cloned instance will have the same instance references as an origin one has? For a primitive `int` field, it doesn't matter as well as for a `String` due to `String` pooling. So, in this case, the standard `Object`s `clone` has the same behaviour with some optimisations. – Andrew Tobilko Oct 30 '16 at 13:19
  • @Redcoatwright, the `CloneNotSupportedException` is a checked exception that will be thrown when your class doesn't provide cloning (doesn't implement the `Cloneable` interface) – Andrew Tobilko Oct 30 '16 at 13:31
  • Josh Bloch says that [clone is broken](http://www.artima.com/intv/bloch13.html), and that you should [use a copy-constructor instead](http://stackoverflow.com/q/2427883/5221149). – Andreas Oct 30 '16 at 13:42
  • @AndrewTobilko yes calling `super.clone()` in this case might have worked as well because the id is primitive and String is immutable, but if the `Product` class had another reference, let's say `Price` as field, then the clone method from the super class wouldn't work – Merve Sahin Oct 30 '16 at 15:13
  • @Redcoatwright the `CloneNotSupportedException` will only be thrown when your class does not implement the `Cloneable` Interface AND calls `super.clone()`, as long as you don't invoke it in the overridden `clone` method, you don't need to implement the Interface – Merve Sahin Oct 30 '16 at 15:19