5

Javaで次のコードを持つ

public Polynomial multiply(Polynomial aPolynomial){
    Polynomial ret = new Polynomial();
    for (Tuple i: this.pol){
        Polynomial temp = aPolynomial.clone();
        System.out.print(temp);
        for (Tuple j: temp.pol){
            j.setCoef(j.getCoef() * i.getCoef());
            j.setPower(j.getPower() + i.getPower());
        }
        ret = ret.add(temp).clone();
    }       
    return ret;
}

System.out.print(temp)常に異なる値の出力として取得します。これは、aPolynomialget が実行時にどこかで変更されることを意味します。

変更Polynomial temp = aPolynomial.clone();:

LinkedList<Tuple> list1 = (LinkedList<Tuple>) aPolynomial.pol.clone();
Polynomial temp = new Polynomial(list1);

System.out.print(temp)ループの実行ごとに出力が異なるため、出力も役に立ちません。

私の間違いはどこですか?

編集:

public Polynomial clone() {
    try {
        return (Polynomial)super.clone();
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
    return null;
}

と を印刷するhashCode()tempaPolynomial2 つの異なる値が得られます。

aPolynomialループhashCodeのすべての実行で同じです。for

コメントのいくつかの質問への回答:

Polynomial私が関係する限り、どこからも継承しないので、super.clone()参照しますObject

私には独自のtoString方法があります。

4

2 に答える 2

4

Java の Object#clone() はデフォルトで浅いコピーを行うと確信しています。つまり、オブジェクトの新しいインスタンスが作成されますが (つまり、"x.clone() != x")、メンバー フィールドは直接コピーされます。これは、メンバーとして参照がある場合、値ではなくアドレスがコピーされることを意味します。したがって、同じオブジェクトを内部的に指すクローンがあります。クローン内のオブジェクトの状態を変更すると、元のオブジェクトの状態が変更されます。

メンバーの新しいインスタンス(あなたの場合はタプルだと思います)も作成する深い copy() を実行して、同じオブジェクトを指さないようにする必要があります。これは自分で実装する必要があります。

clone() を使用することは悪い習慣と見なされていると言われているので、それを行うべきではありません (特に Bloch の clone() とコピー コンストラクターを探してください)。コピー コンストラクタ (オブジェクトと同じ型の引数を取り、それをテンプレートとして使用するコンストラクタ) の他に、特別なディープ コピー ライブラリもあります。または、オブジェクトをシリアル化してそのようにコピーすることもできますが、それは難しい方法が好きな場合のみです。

@Edit: これは彼がそれについて少し話すインタビューですhttp://www.artima.com/intv/bloch13.html . 彼の全文については、Effective Java 2nd Editionを参照する必要があります。

于 2013-10-18T18:58:34.653 に答える