0

なぜ次のことが起こるのかを知る必要があります。このコード (最後の 2 つのブロック) では、まったく同じ出力が期待されますが、ローカル オブジェクト (リスト内のものへの単なる参照ですよね?) は古い状態にありますが、リストを更新しました。ゲームコードに同様のコピー手順があるため、バグがあります(タイルベースのオブジェクトは位置を交換するので、参照を交換するだけではいけないと思いました...)

例:

package game;

import java.util.ArrayList;


public class Tester {
private String s;
private Foo foo;

public Tester(String s, String f) {
    this.s = s;
    this.foo = new Foo(f);
}

class Foo {
    private String f;

    public Foo(String f) {
        this.f = f;
    }
}

@Override
public String toString() {
    return foo.f + ":" + s;
}
public void swap(Tester other) {
    String tempS = this.s;
    Foo tempFoo = this.foo;

    this.s = other.s;
    this.foo = other.foo;
    other.s = tempS;
    other.foo = tempFoo;

}



public static void main(String[] args) {
    ArrayList<Tester> test = new ArrayList<Tester>();
    test.add(new Tester("First", "1"));
    test.add(new Tester("Second", "2"));

    System.out.println("After initializing list");
    for (Tester t : test) {
        System.out.println(t);
    }

    Tester first = test.get(0);
    Tester second = test.get(1);
    Tester tmp = first;

    first = second;
    second = tmp;

    System.out.println("\nAfter temps");
    System.out.println(first);
    System.out.println(second);

    System.out.println("\nList changed after temps?");
    for (Tester t : test) {
        System.out.println(t);
    }

    System.out.println("\nAfter swap");
    first.swap(second);
    System.out.println(first);
    System.out.println(second);

    System.out.println("\nList after swap");
    for (Tester t : test) {
        System.out.println(t);
    }
}
}

そして出力:

After initializing list
1:First
2:Second

After temps
2:Second
1:First

List changed after temps?
1:First
2:Second

After swap
1:First
2:Second

List after swap
2:Second
1:First

私は少し不明確だったと思います.私は常に最初に2番目(オブジェクト)を印刷するので、「スワップ後」は「スワップ後のリスト」とまったく同じように見えるはずです.リストはローカルオブジェクトのスワップ後に変更されました,ローカルオブジェクト(繰り返しますが、リスト内のものへの単なる参照ですか?) 持っていません。

答えのコメントへ:私の混乱が解消され、問題が解決されたときに、オブジェクトへのリストの実際の参照を取得できるかどうかを尋ねていたので、それを別のものに向けると、リストも自動的にそれは別のことです。以下の例では、最初に属性を持つFoo aオブジェクトを指していますが、この参照は から取得しました。これで、リストを指すと、引き続き が指されます。 FooAlist.get()new Turtles()Foo with Aここに画像の説明を入力

タートルを指すと、配列リストがタートルを指すように、「ハード」リファレンスを望んでいました。 ここに画像の説明を入力

これによりスワッピングが簡単になりますが、これを行うことができるリストを実装する方法はまだわかりません (可能な場合)。これは、私のゲームの特定のニーズに非常に適しています。

4

2 に答える 2

3

オブジェクトを操作するときに心に留めておく必要があるのは、オブジェクトを保持する変数は実際にはオブジェクトを表していないということです。変数の値は、オブジェクトが存在する場所へのメモリ内のポインターです。

特定のタイプのオブジェクトの ArrayList は、拡張により、実際にはオブジェクトを保持しません。オブジェクト参照、またはメモリ内のオブジェクトの場所へのポインターを保持します。

あなたが言う時:

Object a = new Object();
Object b = new Object();
a = b;

へのポインターaの値に設定しています。つまり、 と の両方がメモリ内の同じオブジェクトを指しているため、一方を変更すると他方が変更されます。 bab

これを念頭に置いて、あなたの質問に答えてください。ArrayList から 2 つのオブジェクト参照を取得してからそれらを交換すると、オブジェクトへの参照が交換されたことになります。ただし、参照は ArrayList 内の場所を変更していません。これにより、最初の 3 つの出力が説明されます。

ただし、内部スワップを実行すると、各オブジェクトに格納されている値が変更されます。これは、1 番目と 2 番目のオブジェクトへのポインタがメモリ内で同じままであっても、それらの内部情報が交換されたことを意味します。

これにより、最後の 2 つの出力が説明されます。

(注: これは、 equal toSystem.arraycopyを設定する代わりに使用する必要がある理由でもあります。後者を行う場合、 a を変更すると b が変更されます。)int[] aint[] b

于 2013-04-07T20:16:00.747 に答える