Welcome to Our Website

Javaの浅いコピーと深いコピー

無料のJava8コースのこの記事では、深いコピーと浅いコピーの違いについて説明します。 スライドと記事をPDFとしてダウンロードすることができます。

コピーとは何ですか?

まず、Javaのコピーが何であるかを強調したいと思います。 まず、参照コピーとオブジェクトコピーを区別してみましょう。 参照コピーは、名前が示すように、オブジェクトを指す参照変数のコピーを作成します。, Carオブジェクトがあり、myCar変数がそれを指していて、参照コピーを作成すると、二つのmyCar変数がありますが、まだ一つのオブジェクトがあります。

例1

オブジェクトコピーは、オブジェクト自体のコピーを作成します。 したがって、carオブジェクトを再びコピーした場合、オブジェクト自体のコピーと、そのコピーされたオブジェクトを参照する第二の参照変数を作成します。

例2

オブジェクトとは何ですか?,

ディープコピーとシャローコピーはどちらもオブジェクトコピーの一種ですが、実際にはオブジェクトとは何ですか? 多くの場合、私たちがオブジェクトについて話すとき、私たちは謙虚なコーヒー豆のように、さらに分解することはできません単一のユニットとしてそれ しかし、それは単純化され過ぎています。

例3

Personオブジェクトがあるとします。 例4でわかるように、Personオブジェクトは実際には他のオブジェクトで構成されています。 PersonにはNameオブジェクトとAddressオブジェクトが含まれます。, Addressオブジェクトは、StreetオブジェクトとCityオブジェクトで構成されます。 この話者本稿では、私は実際に話したこのネットワーク全体をサポートします。

例4

なぜこのPersonオブジェクトをコピーしたいのですか? 通常はクローンと呼ばれるオブジェクトコピーは、元のオブジェクトを保持しながら、オブジェクトを変更または移動する場合に作成されます。 別の記事で学ぶことができるオブジェクトをコピーするには、さまざまな方法があります。, この記事では、特にコピーコンストラクタを使用してコピーを作成します。

シャローコピー

まず、シャローコピーについて話しましょう。 浅いコピーオブジェクトのコピーのオブジェクト、なかなかできないのでコピーの内側のオブジェクト。 “内部オブジェクト”は元のオブジェクトとそのコピーの間で共有されます。 たとえば、Personオブジェクトでは、二番目のPersonを作成しますが、両方のオブジェクトは同じNameオブジェクトとAddressオブジェクトを共有します。

コーディング例を見てみましょう。 例5では、NameオブジェクトとAddressオブジェクトを含むPersonクラスがあります。, のコピーコンストラクタはoriginalPersonオブジェクトおよびそのコピー基準の変数.

例5

浅いコピーの問題は、二つのオブジェクトが独立していないことです。 ある人の名前オブジェクトを変更すると、その変更は他の人のオブジェクトに反映されます。

これを例に適用しましょう。 参照変数motherを持つPersonオブジェクトがあるとしましょう;次に、motherのコピーを作成し、二人目のオブジェクトsonを作成します。 後でコードの中で、息子がAddressオブジェクトを変更してmoveOut()しようとすると、母親は一緒に移動します!,

Person mother = new Person(new Name(…), new Address(…));Person son = new Person(mother);son.moveOut(new Street(…), new City(…));

例6

これは、例7に示すように、母オブジェクトと息子オブジェクトが同じAddressオブジェクトを共有するために発生します。 一つのオブジェクトのアドレスを変更すると、両方で変更されます!

例7

ディープコピー

シャローコピーとは異なり、ディープコピーはオブジェクトの完全に独立したコピーです。 Personオブジェクトをコピーすると、オブジェクト構造全体がコピーされます。,

例8

ある人のAddressオブジェクトの変更は、例8の図でわかるように、他のオブジェクトには反映されません。 例9のコードを見ると、Personオブジェクトでコピーコンストラクタを使用しているだけでなく、内部オブジェクトでもコピーコンストラクタを使用していることがわかります。

例9

このディープコピーを使用して、例6の母と息子の例を再試行できます。 今、息子は正常に外に移動することができます!,

しかし、それは物語の終わりではありません。 真のディープコピーを作成するには、プリミティブ型と”Immutables”のみが残るまで、Personオブジェクトのネストされた要素をすべてコピーし続ける必要があります。 これをよりよく説明するためにStreetクラスを見てみましょう。

例10

Streetオブジェクトは、String nameとint numberの二つのインスタンス変数で構成され int numberはオブジェクトではなくプリミティブ値です。 これは共有できない単純な値なので、別のインスタンス変数を作成することによって、独立したコピーを自動的に作成します。, 文字列は不変です。 一言で言えば、不変はオブジェクトであり、一度作成されると再び変更することはできません。 したがって、ディープコピーを作成することなく共有できます。

結論

最後に、母と息子の例で使用したいくつかのコーディング技術についてお話ししたいと思います。 ディープコピーでAddressオブジェクトなどのオブジェクトの内部詳細を変更できるからといって、そうすべきという意味ではありません。, これにより、Personクラスが変更に対してより脆弱になるため、コードの品質が低下します–Addressクラスが変更されるたびに、Personクラスにも変更を(潜在的に)適用 たとえば、AddressクラスにStreetオブジェクトが含まれなくなった場合、Addressクラスに加えた変更の上にPersonクラスのmoveOut()メソッドを変更する必要があります。

この記事の例6では、浅いコピーと深いコピーの違いをよりよく説明するために、新しいStreetとCityオブジェクトを使用することだけを選択しました。, 代わりに、代わりに新しいAddressオブジェクトを割り当て、例10でわかるように、浅いコピーと深いコピーのハイブリッドに効果的に変換することをお勧めします。

Person mother = new Person(new Name(…), new Address(…));Person son = new Person(mother);son.moveOut(new Address(...));

例11

オブジェクト指向の用語では、これはカプセル化に違反するため、避ける必要があります。 カプセル化はオブジェクト指向プログラミングの最も重要な側面の一つ この場合、PersonクラスのAddressオブジェクトの内部詳細にアクセスすることで、カプセル化に違反していました。, これは、AddressクラスにPersonクラスを絡み合わせているため、コードに害を与え、Addressクラスを変更すると、上で説明したようにPersonクラスに害を与える可能性があ あなたは明らかにコーディングプロジェクトを持っているためにあなたの様々なクラスを相互接続する必要がありますが、あなたは二つのクラスを

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です