-1

I am trying to make a copy of an object to make some tests on it without affecting the original object. I made this copy() function but the original object is still affected.

Inside the class "I" I have this copy function:

@Override
public Piece copy() {
    I newPiece = new I(blocks[0], blocks[1], blocks[2], blocks[3]);
    newPiece.STATUS = this.STATUS;
    newPiece.FORM = this.FORM;
    return newPiece;
}

and I try to make a copy like this:

Piece rotated = piece.copy();
rotated.changeForm();

Class "I" is a subclass of the abstract class Piece with the abstract method copy(). when I do the changeForm() in the copied object it affects the original one too.

SOLVED

the Block objects were passed as reference too so I needed to add a copy() method even for the type Block. Code changed this way:

    @Override
public Piece copy() {
    I newPiece=new I(blocks[0].copy(),blocks[1].copy(),blocks[2].copy(),blocks[3].copy());
    newPiece.STATUS=this.STATUS;
    newPiece.FORM=this.FORM;
    return newPiece;
}
Ivano Donadi
  • 377
  • 1
  • 13
  • What's the type of `blocks`? – Eran Jan 06 '16 at 12:47
  • I the content of blocks are reference types, you have to copy them too. – jHilscher Jan 06 '16 at 12:48
  • 1
    if you make a copy by setting objects from the original as properties from the copy, making changes to those same properties will affect the properties from the original and the copy – Tom Jan 06 '16 at 12:50
  • Possible duplicate of [How do I copy an object in Java?](http://stackoverflow.com/questions/869033/how-do-i-copy-an-object-in-java) – Erick G. Hagstrom Jan 06 '16 at 12:59

5 Answers5

2

If the contents of blocks are reference types, you will also have to copy them.

Alternatively you could just make a new constructor for Piece and use it.

Piece newPiece = new Piece(oldPiece.thing1(), oldPiece.thing2().....);
J0B
  • 1,648
  • 1
  • 12
  • 24
2

Every type of Piece attributes or fields that is not a primitive type should be copied too.
So the values of STATUS, blocks[1], blocks[2], blocks[3] and FORM.

I hope it helps.

Leonid Glanz
  • 1,261
  • 2
  • 16
  • 36
2

This is the problem, in your copy constructor:

Piece rotated=piece.copy();

That's just copying the reference to the Piece. Both objects will still refer to the same object.

You can use:

Piece rotated = new Piece(piece.copy());

rudi Ladeon
  • 624
  • 6
  • 11
2

You're not changing the new object, you're changing its contents. Unfortunately, the original object has the same contents, so it appears as though you had done something to the original object.

You have made what is called a shallow copy. It would appear that you need to make a deep copy, which involves making copies of the contents of the original object. In your case, you need to make a copy of blocks[0], blocks[1], etc.

The question that may haunt you is how deep that copy must be. You will no doubt find out, but you may have to go deeper than it would appear at first.

Erick G. Hagstrom
  • 4,873
  • 1
  • 24
  • 38
1

As previous authors mention you should make a deep copy of object, but with your code you're only making a shallow copy.

The fastest and easiest way to deep copy an object in java is to serialize() it and deserialize().

Assuming all your classes implement java.io.Serializable interface:

public static <T extends Serializable> T copy(T orig) {

    T obj = null;
    try {
        // Write the object out to a byte array
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(orig);
        out.flush();
        out.close();

        // Make an input stream from the byte array and read
        // a copy of the object back in.
        ObjectInputStream in = new ObjectInputStream(
                new ByteArrayInputStream(bos.toByteArray()));
        obj = (T) in.readObject();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException cnfe) {
        cnfe.printStackTrace();
    }
    return obj;
}
WeMakeSoftware
  • 9,039
  • 5
  • 34
  • 52