拡張forのコードトレース
基本forと拡張forを選び分ける演習です。元の配列、各回の変数、最終出力を分けて書き、代入先がどこかを確かめます。
この単元で学ぶこと
- 拡張forで配列を走査する
- ループ変数への代入と配列要素の更新を区別する
- 添字が必要な処理で基本forを選ぶ
本文解説
集計の準備 int[] a={3,5,7}; int sum=0; for(int x:a){sum+=x;}は15です。添字を足す基本forのsum+=iなら0+1+2=3になり、要素を足す処理とは違います。値と位置を二列に分けて追います。
倍率を変数へ代入 for(int x:a){x*=2;}だけでは元のaは{3,5,7}のままです。本体でxを表示すると6、10、14ですが、ループ後の配列を表示すると元の値です。同じ表示位置で比較することが必要です。
配列を実際に更新 for(int i=0;i<a.length;i++){a[i]*=2;}なら要素は{6,10,14}になります。配列更新を拡張forの変数更新へ機械的に書き換えると結果が変わります。結果を確かめるループは更新後に置きます。
参照先と再代入を続ける StringBuilder[] a={new StringBuilder("A")}; for(StringBuilder x:a){x.append("B");x=new StringBuilder("C");x.append("D");}ではa[0]はABです。最初のappendは共有先、再代入後のappendは新しいオブジェクトへ作用します。
二つの要素が同じ対象を指す StringBuilder b=new StringBuilder("A"); StringBuilder[] a={b,b}; for(StringBuilder x:a){x.append("X");}ではbはAXXです。配列要素数は2でも対象オブジェクトは一つです。各回でその同じ対象を変更します。
nullを要素として含む String[] a={"A",null,"B"}; int n=0; for(String x:a){if(x!=null)n+=x.length();}は2です。nullを除く条件がメソッド呼出しより前にあります。配列参照全体がnullなら、この本体の条件まで到達できません。
入れ子の走査 int[][] a={{1,2},{3}}; int s=0; for(int[] row:a){for(int x:row){s+=x;}}は6です。外側は行配列、内側はint値を受け取ります。行ごとの長さは異なっていてよく、空の行なら内側だけ0回です。
照合の手順 要素を足す基本forと拡張forを別々に動かし、同じ配列なら同じ集計になることを確認します。その後、変数への代入、配列更新、可変対象の変更を一つずつ追加します。型が違う例はコンパイル結果から先に分類します。
図解
重要ポイント
- 拡張forの変数は要素であり添字ではない。
- 変数への代入だけでは元の配列要素を置き換えない。
- 参照先の可変オブジェクトは変更できる。
- 空配列とnull配列を区別する。
間違えやすい点
- x++でint配列を更新したつもりにならない。
- Stringへの再代入とStringBuilderの変更を混同しない。
- 位置・逆順が必要な処理を拡張forだけで無理に書かない。
用語解説
- 拡張for
- 配列やIterableから要素を順次受け取る繰返し。
- ループ変数
- 各回の要素を受け取る本体内の変数。
- 参照
- オブジェクトを指し示す値。
- 可変オブジェクト
- 生成後に内部状態を変更できるオブジェクト。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
確認問題の出題・採点や学習履歴の保存にはログインが必要です。