配列参照渡し、ガベージコレクション vol.25
今回は題名通り二つのことを紹介していく。
参照渡しについては知っていただきたい。
1.参照渡し
例を出そう
int i = 50;
int x = i;
x = 60;
System.out.println(i);
System.out.println(x);
このように記述した普通の変数をコンソールに表示させると
50
60
のように表示させられる。
配列の場合で書いていこう。
int[] number = { 50, 80, 90 };
int[] score = number;
score[0] = 20;
score[1] = 30;
score[2] = 40;
for (int i = 0; i < score.length; i++) {
System.out.println("score" + score[i]);
System.out.println("number" + number[i]);
}
先ほどより少しややこしく見えるがやっていることは、基本的には変わらない。
"score" + score[i]や"number" + number[i]とあるが、どちらの変数かわかるようこのように記述した。
予想としては
score20
number50
score30
number80
score40
number90
となると思う。
コンソールに表示してみよう。
score20
number20
score30
number30
score40
number40
このようになった。
予想と違う。
なぜこうなるのか?
普通の変数の場合はデータそのまま記憶され、代入した時もデータの引き継げだが、配列型変数の場合は、データの住所のようなものが記憶される。
家の住所で例えてみると、先ほどの配列numberが私の家の住所を記憶していたとする。
そのあとにscoreに私の家の住所を記憶させた。
どちらも私の家の住所を記憶している状態だ。
score[0] = 20;
score[1] = 30;
score[2] = 40;
を家で例えると、家具を変えたとする。
家の住所は変わらないが、家の中が変わった。
numberとscoreが記憶している住所は同じであり、中身が変わってしまうと、他に同じ住所を記憶している配列に影響を与えてしまう。
実際にデータの住所を見てみよう。
int[] number = { 50, 80, 90 };
int[] score = number;
System.out.println(score);
System.out.println(number);
このように記述しコンソールに表示させる。
[I@4361bd48
[I@4361bd48
よくわからない文字列が出てきた。これがデータの住所だ。
例えば、このように記述すれば参照渡しは回避できる。
int[] number = { 50, 80, 90 };
int[] score = { 50, 80, 90 };
System.out.println(score);
System.out.println(number);
コンソールに表示させると
[I@4361bd48
[I@762efe5d
もしくはこのような書き方もある。
int[] number = { 50, 80, 90 };
int[] score = new int[number.length];
for(int i = 0 ; i < number.length ; i++) {
score[i] = number[i];
}
System.out.println(score);
System.out.println(number);
先ほどと結果は変わらないが、このような書き方もあることを伝えたかった。
これらのように書くことで、データの住所が変わった。これで参照渡しが起きない。
参照渡しは場合によって使う場合もあるが、知らなければ予想外のことが起きることがあるので知っていただきたい。
2.ガベージコレクション
簡単に言うと宣言していた配列を破棄するということ。
もういらないから使えなくするよということ。
int[] number = { 50, 80, 90 };
number = null;
number[0] = 1;
System.out.println(number[0]);
の様に、numberをnull宣言した。
その結果実行すると
NullPointerExceptionという例外が発生した。エラーのことだ。
これは存在していないよというような感じだ。
こちらに詳しく書いてある。
このようにnull宣言するだけで配列が使えなくなってしまう。
int[] number = { 50, 80, 90 };
number[0] = null;
System.out.println(number[0]);
ちなみにint型の配列でこのようなことはできない。
コンパイルエラーとなってしまうので、実行すらできない。
String型の配列であれば実装できる。
String[] number = { "50", "80", "90" };
number[0] = null;
System.out.println(number[0]);
コンソールにはnullと表示される。
今回のことをまとめると
配列同士を=すると中身のデータではなく住所が移されるため片方の中身を変えてしまうと、もう一つの穂まで影響されてしまう。
配列を要素数着けずにnullするとその配列は使えなくなる。
長くなったが以上。
では、また次回
元体育会系文系エンジニア石黒