Snowdrama
Snowdrama

Reputation: 415

Java, is this a Deep copy?

I cant seem to get a clear precise answer by reading any of the similar questions, I'm trying to deep Clone an object in Java using a copy constructor is this a deep copy:

public class Tile{
    Image sprite = null;
    int x = 0;
    int y = 0;
    public Tile(Image setImage, int sX, int sY){
         this.sprite = setImage;
         this.x = sX;
         this.y = sY;
    }
    public Tile(Tile copyTile){
         this.sprite = copyTile.sprite;
         this.x = copyTile.x;
         this.y = copyTile.y;
    }
    public void setNewLocation(int sX, int sY){
         this.x = sX;
         this.y = sY;
    }
}

Then when I create my tile map I could do something like this

List<Tile> tileList = new List<Tile>();
Tile masterGrassTile = new Tile(grassImage, 0,0);
tileList.set(0,new Tile(masterGrassTile));
tileList.set(1,new Tile(masterGrassTile));
tileList.get(0).setNewLocation(0,32);
tileList.get(1).setNewLocation(0,64);

If i were to render both tiles at their respective locations would that work? or was the assignment tileList.get(1).setNewLocation(0,64); effecting like a reference and all of them have the same location as the last assignment.

Upvotes: 7

Views: 2274

Answers (5)

Subir Kumar Sao
Subir Kumar Sao

Reputation: 8401

is this a deep copy ?

No, it's not because this.sprite = copyTile.sprite; both objects of Tile is refering to same object of Image.

If i were to render both tiles at their respective locations would that work? or was the assignment tileList.get(1).setNewLocation(0,64); effecting like a reference and all of them have the same location as the last assignment.

No, the values of x and y are independent in the two objects of Tiles and code should work and both the objects will have different x and y values.

Upvotes: 11

Kevin Bowersox
Kevin Bowersox

Reputation: 94479

First, lets review the differences between a deep and a shallow copy.

A shallow copy points to the same references as the source. So if make a copy of instance A named B any changes to fields containing objects in B will modify these fields in A since they are pointing to the same reference.

A deep copy has independent fields/references, it does not point to the source's references. A change to a field/property on the copy will not impact the source's fields/properties.

In your case, I believe you have made a shallow copy since your assigning the reference of sprite field from the source to the copy's sprite field.

To illustrate this, I have modified the Tile classes source to expose the Image and have mocked an Image class.

Modifications for Proof of Concept

class Tile{
        /* Rest of Class*/
        //Additions
    public Image getSprite() {
        return sprite;
    }
    public void setSprite(Image sprite) {
        this.sprite = sprite;
    }

}

//Mock
class Image{
    public String name;
    public Image(String name){
        this.name = name;
    }
}

Proof of Concept

public static void main(String[] args) {
    List<Tile> tileList = new ArrayList<Tile>();
    Tile masterGrassTile = new Tile(new Image("grass.png"), 0,0);

    Tile copyTile = new Tile(masterGrassTile);
    copyTile.getSprite().name = "water.png";

    System.out.println(masterGrassTile.getSprite().name); //Prints water.png
}

Notice how changing the copied instance's sprite property affects the original instances sprite property.

Upvotes: 4

Sami N
Sami N

Reputation: 1180

http://www.oracle.com/technetwork/java/seccodeguide-139067.html#6

If a method returns a reference to an internal mutable object, then client code may modify the internal state of the instance. Unless the intention is to share state, copy mutable objects and return the copy.

So you'd have to actually make a new instance out of Image.

public Tile(Tile copyTile){
     this.sprite = new Image();
     //Then copy the image to the newly instantiated sprite
     this.x = copyTile.x;
     this.y = copyTile.y;
}

Upvotes: 2

Dennis Laumen
Dennis Laumen

Reputation: 3223

No, this is not a deep copy as the same Image object is shared between all object of Tile.

Looking at your example though it appears that this copy would be sufficient for your needs as it allows you to reuse the same Image object on different locations (which presumably is more efficient).

Upvotes: 3

Mr.Me
Mr.Me

Reputation: 9276

In java there are two data types:

  • primitives (float, int , double, boolean ...) which doesn't have concept of deep/shallow copying because they work with assignments.
  • objects where a shallow copy means passing the reference. while a deep copy means having a new object with the same values that the source has.

giving the above your code doesn't satisfy deep copying when passing the Image object. and if you are rendering using that object then that object can only have one position. which will cause your code to render both tiles at the same place.

To fix this you should clone your Image object.

 public Tile(Tile copyTile){
     this.sprite = copyTile.sprite.clone();
     this.x = copyTile.x;
     this.y = copyTile.y;
}

Upvotes: 3

Related Questions