7

同様の質問を読んでも、明確で正確な答えが得られないようです。コピーコンストラクターを使用してJavaでオブジェクトのクローンを作成しようとしています。これは、ディープコピーです。

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;
    }
}

次に、タイルマップを作成すると、次のようなことができます。

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);

両方のタイルをそれぞれの場所にレンダリングするとしたら、それは機能しますか?または、割り当てtileList.get(1).setNewLocation(0,64);でした。参照のように効果があり、それらはすべて最後の割り当てと同じ場所にあります。

4

5 に答える 5

11

これは深いコピーですか?

いいえ、それはのthis.sprite = copyTile.sprite;両方のオブジェクトがのTile同じオブジェクトを参照しているからではありませんImage

両方のタイルをそれぞれの場所にレンダリングするとしたら、それは機能しますか?または、割り当てtileList.get(1).setNewLocation(0,64);でした。参照のように効果があり、それらはすべて最後の割り当てと同じ場所にあります。

いいえ、xとyの値はの2つのオブジェクトで独立しておりTiles、コードは機能するはずであり、両方のオブジェクトのxとyの値は異なります。

于 2013-03-25T09:02:15.427 に答える
4

まず、深いコピーと浅いコピーの違いを確認しましょう。

浅いコピーは、ソースと同じ参照を指します。したがって、オブジェクトを含むフィールドに変更を加えたA名前のインスタンスのコピーを作成すると、同じ参照を指しているため、これらのフィールドが変更されます。BBA

ディープコピーには独立したフィールド/参照があり、ソースの参照を指していません。コピーのフィールド/プロパティを変更しても、ソースのフィールド/プロパティには影響しません。

あなたの場合、ソースからのスプライトフィールドの参照をコピーのスプライトフィールドに割り当ててから、浅いコピーを作成したと思います。

これを説明するために、Tileクラスのソースを変更してを公開Imageし、クラスをモックしましたImage

概念実証のための変更

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;
    }
}

コンセプトの証明

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
}

コピーされたインスタンスのスプライトプロパティを変更すると、元のインスタンスのスプライトプロパティにどのように影響するかに注意してください。

于 2013-03-25T09:10:43.040 に答える
3

Javaには、次の2つのデータ型があります。

  • プリミティブ(float、int、double、boolean ...)は、割り当てで機能するため、ディープ/シャローコピーの概念がありません。
  • 浅いコピーが参照を渡すことを意味するオブジェクト。一方、ディープコピーとは、ソースと同じ値を持つ新しいオブジェクトを持つことを意味します。

Image上記のコードを指定しても、オブジェクトを渡すときにディープコピーを実行することはできません。そのオブジェクトを使用してレンダリングしている場合、そのオブジェクトは1つの位置しか持つことができません。これにより、コードは両方のタイルを同じ場所にレンダリングします。

これを修正するには、Imageオブジェクトのクローンを作成する必要があります。

 public Tile(Tile copyTile){
     this.sprite = copyTile.sprite.clone();
     this.x = copyTile.x;
     this.y = copyTile.y;
}
于 2013-03-25T09:05:26.253 に答える
3

いいえ、これはディープコピーではありません。同じImageオブジェクトがTileのすべてのオブジェクト間で共有されているためです。

あなたの例を見ると、このコピーは異なる場所で同じImageオブジェクトを再利用できるので(おそらくより効率的です)、ニーズには十分であるように見えます。

于 2013-03-25T09:05:41.667 に答える
2

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

メソッドが内部の可変オブジェクトへの参照を返す場合、クライアントコードはインスタンスの内部状態を変更する可能性があります。状態を共有することが意図されていない限り、可変オブジェクトをコピーして、そのコピーを返します。

したがって、実際にから新しいインスタンスを作成する必要があります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;
}
于 2013-03-25T09:06:05.273 に答える