先日業務で拡張for文を扱う場面があり、少々はまったのでメモ。
まず、拡張for文とは何かをまとめておく。
Hoge hoge1 = new Hoge();
Hoge hoge2 = new Hoge();
Hoge hoge3 = new Hoge();
List<Hoge> hogeList = new ArrayList<>();
hogeList.add(Hoge1);
hogeList.add(Hoge2);
hogeList.add(Hoge3);
// ここから拡張for文
for(Hoge hoge : hogeList){
hoge.~~なにかしらの処理
}
とまあこんな感じにコードを記載する。
すると、HogeListの要素が一つづつhogeに取り出されて、すべての要素に対して繰り返し処理を行うことができる。
hogeに代入されるもの
ここで気になったのが、hogeには参照が渡されるという点。
hogeに参照が渡される以上、拡張for文の中でhogeに対して何かしらの処理を施した場合、
hogeListの要素が指している参照先が更新されることになる。要はhogeListの中身が更新される。
ここまでは参照型の仕組みについて把握していれば理解はできた。
参照型でもStringの場合は話が違うらしい。
問題はStringを扱った場合。ここでString型に対する知識不足が露呈。理解が追い付かなくなった。
まずは事象の整理から。
String A = "AAA";
String B = "BBB";
String C = "CCC";
List<String> stringList = new ArrayList<>();
stringList.add(A);
stringList.add(B);
stringList.add(C);
for(String str : stringList){
str = "Foo";
}
for(String str : stringList){
System.out.println(str);
}
結果
+++++++++++++++++++++++++++++++++++++++++
AAA
BBB
CCC
+++++++++++++++++++++++++++++++++++++++++
for文でListの中身をすべて"Foo"に上書きしたのに、なぜか初期化した状態から変わっていない。
なぜ?と思いながらあれこれ考えているうちに、曖昧ながらなんとなく思い出してきた。
「Stringは不変」みたいな性質あったなぁと。
そもそもStringの不変性についてそこまでしっかり理解しているわけではなかったので、もしかしてこれが関係しているのか?と気が付いたはいいものの結局どういう理屈なのかは未だに理解できていない。
デバッグしてみて、Stringの場合は参照渡しではなく値渡しになるんだなというところで一旦着地した。
結局根本的なところはまだ理解できていない
今回は拡張for文をきっかけに、自分がStringに対してすごく無知であることに気づかされた。
「Stringの不変性」このキーワードで少し勉強します。