制御文
制御文とは処理の流れを制御するための文です。
処理の流れを制御するといっても、自由気ままに処理が定義出来れば良いというわけではありません。「構造化プログラミング」では処理は「順次」、「分岐」、「繰返し」の3種類の組み合わせで定義すべきと推奨されています。
それ以外の「移動(goto文)」などを使うとプログラムはいわゆるスパゲティ状態になり、作者以外はもちろん作者でさえも時間が経つと処理の流れを把握しずらくなってしまうといわれます。
「順次」は何々をしたら、次に何をする、という処理を次々に行う形態で、コーディングは命令文を順次書き連ねていきます。
「分岐」は何々の条件では何を行い、その条件でなければ何を行うという形態で、コーディングはif-else文、if-else if文、switch文を使って命令文を区分けして書きます。
「繰返し」はある条件が有効な間は何を行い続け、条件が有効で無くなったら次の命令に移るという形態で、コーディングはwhile文、do-while文、for文、拡張for文を使って記述します。
言語仕様として難しい点はありませんが、「分岐」と「繰返し」には注意すべき点がいくつかあります。
for文
for(初期化文; 繰返し条件文; 繰返しが終わる毎に行う更新文) { 繰り返し時に行う処理 }
for文の構文で注意すべき点は、
for文の初期化文、条件文、更新文のうち、初期化文と更新文は複数記述できますし、省略することも出来ます。条件文は一つしか記述できず省略することはできません。複数の条件が必要な場合は論理演算子を使って複合条件にします。
初期化文で複数の変数を宣言する場合、変数は同じ型でなければいけません。異なる型の変数を複数宣言すると、コンパイルエラーが発生します。
初期化文で宣言した変数のスコープはfor文のブロック内であり、for文のブロック外で参照するとコンパイルエラーになります。
繰返し条件の評価は繰返し処理の前に行われるので、条件式の指定を誤ると繰返し処理を一度も行わない場合もあります。
public class ForSample { public static void main(String args[]) { for(int i=0; i<0; i++) { System.out.println("forループの実行ブロック"); } System.out.println("ここはforループの外です"); } }
実行結果
繰返し処理を行っていません。
>java ForSample ここはforループの外です >
到達不能文
if文やWhile文、for文では条件として論理値を記述する場合がありますが、論理値としてfalseを記述すると命令文を全く実行しなくなってしまいます。Javaではこのような到達不能文が発生すると多くの場合コンパイルエラーを出します。
確かにWhile文、for文ではコンパイルエラーが出ます、しかしif文ではコンパイルエラーは出ません。
この処理の違いはif文の場合、下記のような記述により定数DEBUGをtrue、falseに切り替えて利用する為と想像できます。
if(DEBUG) System.out.println("This is Debug write.");
拡張for文
拡張for文は、ある型のデータ集合から順にデータを呼び出す便利な構文です。しかし、その性質からデータを降順で呼び出したり、一つおきに呼びだすという事は出来ません。従って基本型を収納した一次元配列では標準for文に対する利点は単に記述が簡素化されるだけです。
逆にデータを呼び出すインデックスを指定する必要がないので、標準for文では扱えないHashMap等のint型のインデックスを持たないデータ集合を扱うことが出来ます。
if-else if文
Javaの文は句の句の間で空白だけでなく、改行を挿入してもコンパイルエラーにはなりません。しかし、これは改行を置いた場合の解釈がどう扱われるかという事とは別です。
if-else if文の場合elseとifの間に改行を置くと、if-else if文はif-else文として解釈され、改行後のifはelse文の中のif文として解釈されます。
public class IfElseSample { public static void main(String args[]) { int num = 1; if(num != 1) System.out.println("ここは印字されません"); else if(num < 1) System.out.println("ここは印字されません"); else if(num == 1) System.out.println("ここは印字されます"); else if(num == 1) System.out.println("ここは印字されません"); } }
実行結果
>java IfElseSample ここは印字されます >
break文、continue文
for文やwhile文、do-while文ではbreak文やcontinue文を使って細かな分岐や繰返し制御が行えます。
break文はその場で実行中のループ抜けます。
ネストされたループの場合はbreak文の置かれたレベルの繰返しを終わるのであって、外側にも別の繰返しがあるケースですべての繰返しを終わりたい場合は外側の繰返しの先頭にラベルを置いて、break文でそのラベルを記述します。
loopExit: for(int i=0; i<array.length; i++) { for(int J=0; j<array[i].length; j++) { if(array[i][j] == 99) break loopExit; } }
continue文はcontinue文以降の命令文をスキップして次の繰返し処理を継続実行します。continue分もラベルを使って処理の継続先を指定することが出来ます。
do-while文
doのあとにはセミコロンがなく実行ブロックが続きます。実行ブロックを{ }で括らない場合は、実行文は1文で2文以上を書くとコンパイルエラーになります。