こんにちは、現役SEの「とも」です。
今回は、「参照型」に入る前の基礎知識として、メモリについて書いていきたいと思います。これまでの「整数型」「浮動小数点型」「文字型」「真偽値型」は、Javaのプリミティブ型と呼ばれ、Javaが定義している基本型の変数です。
プリミティブ型は、メモリのスタック領域と呼ばれる領域にデータを格納する場所が用意されます。
イメージとしては、下のようになります。
int a = 100;
double b = 1.2345;
char c = 'あ';
boolean d = true;
参照型がプリミティブ型と違う点は、メモリのスタック領域と呼ばれる領域にデータを格納せず、ヒープ領域にデータを格納するという点です。
そして、変数に値として入っているのは、スタック領域に格納されている「データを格納している場所」になります。
この「データを格納している場所」のことを「ポインタ」と言います。
「スタック領域」と「ヒープ領域」は、いろいろと動きが違いますが、ここでは細かいことは気にせず、「参照型は変数にポインタを格納している」と覚えておけば問題ありません。
参照型の例として、String型を見ていきましょう。
String型とは文字列を扱う変数で、char型と違い1文字だけではなく「複数の文字」が扱えます。
といっても、char型を複数集めて文字列となるようにしている変数です。
String型を定義した時、メモリの状態は以下のようになります。
String str = "あいうえお";
ただし、javaでは実際に「ポインタの値」を見ることはできず、Javaが値なのかポインタなのかを自動で判断するため、プログラマは「先頭の場所(アドレス)が・・・」なんていう意識をする必要はありません。
C言語や、C++ではポインタは値として直接見ることができるので、アドレス操作で自由度の高い値の操作ができましたが、その反面、値とポインタを意識しなければならずバグも非常に出やすいものでした。
Javaではポインタ操作による値の操作ができなくなっているので、値なのかポインタなのかを意識する必要はなく、ポインタが原因によるバグは出ない仕組みになっています。
Javaプログラマが、参照型変数で意識するべきは下の2つです。
- メソッドの値の受け渡し
- メモリの解放
「メソッドの値の受け渡し」については、メソッドの説明の際にしたいと思います。
メモリの解放については、以下のように変数にnullを設定します。
これによって、参照されていない領域「あいうえお」は、Javaの「ガベージコレクション」という機能によって解放され再利用可能な領域となります。
String str = "あいうえお";
str = null; //データ”あいうえお”の領域は解放される
では、このメモリの解放をしない場合どうなるのかという話ですが、メモリは有限の資源で限りがあります。
変数にメモリを割り当てし続けると、そのうち使えるメモリの上限に達して、「Out Of Memory」というエラーが発生します。
そうなると、新しく変数のメモリが確保できなくなり、プログラムがエラーで終了することになります。
そうならないように、不要になった変数のメモリは逐次解放しなくてはいけません。
通常Javaでは、プログラムが終了することでその中で使用されていたメモリは解放されます。
そのため、Javaプログラマーとしては、プログラムで動いている最中だけメモリに気を付ければよいです。
通常の利用ではOut Of Memoryにはならないので、注意すべきは「繰り返し処理」内でのメモリの割り当てになります。
基本的に、使用を終えた参照型変数については、最後にnullを設定しておくことでメモリを解放する習慣を身につけておくと良いでしょう。
余計なトラブルは避けることができます。