今回はJavaを用いて配列に対して=によって代入することが誤りであることについて説明します。
単純な値の代入であれば=を利用した代入が可能なのですが、問題になってくるのは配列やクラスなどです。
今回は簡単な配列を使って=での代入がうまくいかないケースを説明し、配列を代入するためにはどうすればいいかについて述べていきます。
配列の変数の場合はただ=を使うだけでは配列を新しく作ってくれない
まず、単純に配列を定義して=だけで代入しようとしてみます。
以下のように処理を定義してみます。
//間違った配列の使い方(イコールでの代入)
public void wrongProcess() {
int[] int1 = {7, 8};
int[] int2;
//int2にint1の内容を複製?
int2 = int1;
//int2の配列の方で足し算を行い、結果をint2[1]に入れる
int2[1] = int2[0] + int2[1];
System.out.println("int1[0]の値は" + int1[0] +"です。");//7が出力される
System.out.println("int1[1]の値は" + int1[1] +"です。");//8が出力される?
System.out.println("int2[0]の値は" + int2[0] +"です。");//7が出力される
System.out.println("int2[1]の値は" + int2[1] +"です。");//15が出力される
}
このプログラムの6行目で、int1の配列をint2に代入しようとしています。
そして、int2側の配列の2番目の要素の値を変えて、int1、int2に入っている値を見てみます。
さて、どうなるでしょうか?
この処理を実行すると以下のような動作になります。
なんと、int2側だけではなくint1側の配列の要素の値も変わってしまいました。
なぜこのようなことが起きたかを説明しますと、6行目の
int2 = int1;
の部分ですが、int1の配列をコピーしてint2に代入したわけではなく、変数int1の参照する配列と同じ場所をint2が参照するようになっただけなのです。
つまり、この処理であればint1とint2は同じ場所の配列を指すようにしただけであり、int2の指す先の配列の値を変えてしまうと、int1側も同じ場所の配列を参照しているため、int1が参照する配列の値も変わってしまいます。
そのため、int1側で値を変えていないはずなのに、int2側の配列の値を変えるとint1側の配列の値も変わってしまったという現象が起きてしまいました。
配列を作成して代入させるにはclone()を使う
先ほどのプログラムでは=で代入したと思っても、実は同じ場所を参照するようになっただけで、配列を丸ごとコピーすることはできませんでした。
配列のコピーをするのに使える手段はいくつかありますが、最もシンプルな手段がclone()という関数を使うことです。
実際にclone()を利用したプログラムを書いてみると以下のようになります。
//正しい配列の使い方(clone()で複製する)
public void rightProcess() {
int[] int1 = {7, 8};
int[] int2;
//int2にint1の内容を複製
int2 = int1.clone();
//int2の配列の方で足し算を行い、結果をint2[1]に入れる
int2[1] = int2[0] + int2[1];
System.out.println("int1[0]の値は" + int1[0] +"です。");//7が出力される
System.out.println("int1[1]の値は" + int1[1] +"です。");//8が出力される
System.out.println("int2[0]の値は" + int2[0] +"です。");//7が出力される
System.out.println("int2[1]の値は" + int2[1] +"です。");//15が出力される
}
このプログラムの6行目ですが、
int2 = int1.clone();
この部分で、int1の配列を複製し、その場所を参照するようにint2が定義されます。
そのため、この処理を行うことで先ほど起きたint2の配列の値を書き換えてint1の配列の値が書き換えられるということはなくなるはずです。
実際に動作を見てみましょう。
このように配列int1の値が書き換わることなく、配列int2の値だけが書き換わりました。
配列を複製して定義する方法は他にもやり方はありますが、ソースコードを一番簡単に書けるのがclone()を使う方法なので、まずはclone()を使う方法を覚えていくとよいかと思います。
まとめ
今回は短い記事となりましたが、以下のことを覚えてほしいと思います。
- 配列をコピーして代入する場合は単純に=を使うだけでは実現できない
- 数値や文字列などの値を代入するだけであれば単純な=を使うだけで十分である
- clone()を使うことで配列を丸ごとコピーして、=の左辺の変数で参照させることが出来るようになる。
今回説明した内容は初歩的な内容ですが、あまりCやJavaを勉強したことがない人にとっては間違えやすい内容になります。
=で配列をコピーして代入してくれるプログラミングの言語は存在しますが、Javaを利用する際はこの考え方を捨てて、きちんとした手順で配列を複製してそこを指すようにプログラムを書くことが大切です。
なお、最初のプログラムのように配列同士をイコールで結ぶ
int2 = int1;
ですが、この処理をわざわざ行うくらいであれば、直接元の配列の値を書き換えたほうが読みやすいプログラムになると思います。
プログラム上は正しい書き方ですが、動作自体は間違ったものになることもあるため、配列のコピーの意味で配列同士を=で結ぶことは避けたほうがいいでしょう。
今回の記事はここまでとなります。
また次回の記事でお会いしましょう。