Reputation: 415
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
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
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
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
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
Reputation: 9276
In java there are two data types:
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