はじめに
forループに限らず、whileループとかif-else文とかtry-catchとか・・・。
いろいろ「ブロック」はあるけれど、その中でしか使わない変数は、ブロックの中で宣言しましょうね、というお話です。
よくない例
List<String> strList = new ArrayList<String>();
String str = new String(); // ←これ!!!
for (int i = 0 ; i <= 10 ; i++) {
str = i + "番目";
strList.add(str);
}
※このプログラムが正しく動くかどうかは置いといて、スコープだけに焦点を当てて話を進めます。
String str
をforループの外で宣言しているので、forループの外側でも使用可能です。
なので、「スコープは可能な限り小さく!」というJavaのセオリーには反しています。
この書き方をした人に聞いてみた
2人ほどこの書き方をしていた人がいたので、「どうしてこういう書き方にしたの?」って聞いてみました。
そしたら
同じ
String str
を使いまわすので、メモリ節約になるかなーと
無駄な変数はたくさん作らないという意味では、決して間違った考え方ではないんですけどね
だけど、スコープが不必要に広がってしまうのでNGです。
よい例
List<String> strList = new ArrayList<String>();
for (int i = 0 ; i <= 10 ; i++) {
String str = new String();
str = i + "番目";
strList.add(str);
}
※上記の「よくない例」と比較するために書きましたが、おそらく実際の現場ではこんなまどろっこしい書き方はしないと思ってます。
※このソースがイケてるかどうかではなく、スコープだけに焦点を当ててます。
String str
を使うのはforループの中だけです。
だったら、forループの中で宣言すれば、スコープは小さくなります。
Javaは「使い終わったらすぐにメモリを開放する」ためのガベージコレクトが機能するので、forループ1回ごとに新しいString str
が作られては解放されていきます。
そのため、あんまりメモリを意識しなくてよいと思います。
まとめ
forループの中だけで使う変数は、forループの中で宣言する。
※一番馴染みのありそうなforループで説明しましたが、if-else文やwhileループなどでも同様です。
乱暴な言い方をすると、迷ったら一旦ループの中に変数を入れてみましょう。
エラーにならなければ、そのまま入れっぱなしでOKです。
おまけ
「よい例」で書いたプログラムは、私の場合は、ここまで整理するかなー。
List<String> strList = new ArrayList<String>();
for (int i = 0 ; i <= 10 ; i++) {
strList.add(i + "番目");
}