2015-11-02 6 views
19

私は、Javaのクローニングがどのように機能するのか、それを使用することの論議を理解します。とにかく私はそれを使用して死んでいると言うことができます。私は次のようにクラスFooのためのcloneメソッドを書きたいの便宜上オーバーライドされた.cloneの内部にキャストしないのはなぜですか?

私の知る限りは安全だろう、これを言うことができるように
@Override 
public Foo clone(){ 
    Foo f = (Foo)super.clone(); 
    //Replace mutable fields 
    return f; 
} 

。しかし、私は、APIのCloneableクラスはこれをしないことに気付きました。これには理由があり、それは悪いスタイルですか?

+1

これは、次のように使用すると便利です。 'Foo foo = ...; Foo bar = foo.clone() 'となります。 – biziclop

答えて

17

Java 5以前では、共変リターン型はまったく許可されていなかったので、Foo clone()はコンパイルさえしませんでした。 多くの場合Cloneableのクラスが長い時間前に書かれているので、それはおそらく大部分のケースの理由です。

clone()はほんの一握りであることが知られているため、新しいクラスではそれを使用していないと思われます。ユーザーがめったに使用しない場合でも、キャストできるとは思わないからです。彼らはいくつかの "clone()"の実装方法を見つけ、古いコードで記述します。

+5

古き良き "それは壊れてしまったので、誰もそれを修正しようと時間を無駄にしようとしたことさえありませんでした"。 – mgarciaisaia

3

Object.clone()すべてのフィールドが元の値と同じ値を持つ新しいオブジェクトを作成します。参照タイプのフィールドの場合、これは新しいフィールドが単に元のオブジェクトと同じオブジェクトへの参照であることを意味します。フィールドはcloneではありません。したがって、多くの場合、デフォルトの実装は共有データにつながり、望ましくない可能性があります。たとえば、ArrayList.clone()がデフォルトの実装を使用した場合、2つのArrayListインスタンスが同じバッキングアレイを共有することになります。

オブジェクトのすべてのフィールドが不変の場合は、結果をsuper.clone()に適切な型にキャストすることをお勧めします。

+1

APIは 'clone()'が何をしているのかかなり曖昧ですが、通常は、クローンされているオブジェクトの内部「深い構造」を構成する可変オブジェクトをすべてコピーし、これらのオブジェクトはコピーを参照します.'なので、 'clone()'は理想的にディープコピーを返すべきです。理想的ですが必ずしも必要ではありません。 – biziclop

+0

フィールドがすべて不変の場合、深いコピーと浅いコピーに違いはありません。 –

+3

それは本当ですが、それはどのように質問に関連していますか?私は少し失われています。 :) – biziclop

3

実際、共用リターンタイプがリリース1.5でジェネリックスの一部として導入されたため、これはJava 1.5のリリース以降、これを行うことをお勧めします。 APIを使いやすくしました(キャスティングは必要ありません)。

ソース(有効なJava第2版)。

関連する問題