LoginSignup
1
1

More than 1 year has passed since last update.

配列とCloneメソッドの挙動について

Posted at

Java Silverの学習中、配列とcloneメソッドの問題とその解説が全く理解できなかったので色々調べた結果、ようやく自分が納得できる形でまとめることができたので、情報整理も兼ねて投稿します。

悩みの種

次のコードを確認し、trueを返すコードとして正しいものを選びなさい。(一つ選択)

char[][] array1 = { { 'a' , 'b' } , { 'c' , 'd' } };

char[][] array2 = array1.clone();

char[] array3 = array1[1].clone();

A. array1[1] == array3

B. array1[1] == array3[1]

C. array1[1] == array2[1]

D. array1.equals(array2)


正解は...

C. array1[1] == array2[1]

解説(長すぎるので少し抜粋)

①Cloneメソッドは新しい配列を作り、その配列に同じ要素への参照をコピーする。

②Cloneメソッドで作られた複製の配列と元の配列は同じ参照先を共有する。

array2 = array1.clone() で、array1の参照先のコピーをarray2に代入している。 
よって、array1とarray2は同じ要素の参照をしていることになり、array1の要素を変更すると、array2が参照している要素も変更される。

④同一性を検証する  == 演算子はtrueと判定される。 よってCが正解になる。

⑤array1の2番目の要素(char配列)のcloneメソッドを使ったarray1[1].clone()では、新しい配列を作り、その配列に同じ要素をコピーし直す。
新しい配列を作っているため、array1とarray3は同じ値を持っている異なる配列への参照を持つことになる。よってAは誤り。

⑥選択肢Bは二次元配列であるarray1の2番目の要素と、一次元配列であるarray3の2番目の要素を比較しているため、コンパイルエラーとなる。

⑦equalsメソッドはオーバーライドされないと同値性ではなく、同一性を検証する(==演算子と同じ)する。
array2には、array1のcloneメソッドの結果作られた新しい配列への参照が入っている。そのため、array1とarray2は異なる参照を持っていることから、equalsメソッドはfalseを戻す。

読解力のない自分用への解説

正直この解説が図解もなく全然意味が分からなかったので、以下のように自分用に解説。

全体イメージ図

スクリーンショット 2022-06-23 3.12.49.png

Cloneメソッドで何が起きているか

①まずメモリ内の8221番地にある既存の配列から、8567番地に同じ要素を持つ配列を新規に作成する。

②変数Array2には、8567番地が代入される。(Array1には、8221番地が代入されている。)

変数同士の比較結果

Array1とArray2はそれぞれ違う番地の値が代入されている。

==演算子による比較と、オーバーライドされていないequalsメソッドは、この番地が同じかどうかを検証するので、

結果はfalseが返される。

dokojavaを使用して実践。

スクリーンショット 2022-06-23 3.23.32.png
結果、
スクリーンショット 2022-06-23 3.25.48.png

要素同士の比較結果

Array1[1] と Array2[1]を比較した場合、Cloneメソッドでは配列内の要素が同じ状態で作成される。
なので、各Indexが参照している参照先(番地)は同じになる。
よってArray1の1番目の配列と、Array2の1番目の配列は、配列の実体自体は違う番地にあるが、各要素が指している次の配列の参照先は同じということになる。
よって要素同士の検証すると、

結果はtrueが返される。

dokojavaを使用して実践。

スクリーンショット 2022-06-23 3.35.34.png
結果、
スクリーンショット 2022-06-23 3.36.19.png

一次元配列の場合

一次元配列の場合も同様。
変数名同士を比較することは、配列の番地を比較することになる。

よって、Array1[1] == Array3 もfalseが返される。
しかし、配列の先の要素は同じものを参照しているので、同じ値でtrueが返される。
スクリーンショット 2022-06-23 3.42.45.png
スクリーンショット 2022-06-23 3.43.56.png

注意点

全体イメージ図とここまでの説明を振り返れば当然のことだが、既存の配列とCloneしてできた配列は、要素は同じだが それぞれ独立した配列である。
よって格納している要素にもよるが、片方の配列の要素を変更しても、もう一方が影響を受けるわけではない。

一次元データ型

スクリーンショット 2022-06-23 4.02.45.png

スクリーンショット 2022-06-23 4.03.59.png
スクリーンショット 2022-06-23 4.04.37.png

多次元

スクリーンショット 2022-06-23 4.08.06.png
スクリーンショット 2022-06-23 4.08.44.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1