1-5-1:処理の流れと制御構造


・ Javaのプログラムの処理はどんな順序で実行されるのでしょうか? まず以下のサンプルで説明しましょう。


public class FlowTest1 {
    public static void main( String[] args ) {
        System.out.println( "1st message" );
        System.out.println( "2nd message" );
        if( 10 > 100 ) {
            System.out.println( "select true" );
        }
        else {
            System.out.println( "select false" );
        }
        System.out.println( "last message" );
    }
}

・ Javaのプログラムの処理は、JVMに読み込まれたクラスの main()という名前のメソッドから開始されます。 (厳密には、その前にstaticなフィールドが初期化する処理が先に実行されます。) javaコマンドで直接読み込まれるクラスには必ず main()が存在しなくてはいけません。 そうでないと実行時のエラーとなります。 また、単に main()という名前だけではなく、public かつ static であること、 メソッドの型は void型であること(計算結果を返さない)、 引数に Stringクラスの配列が唯一与えられることも必須です。 これらのすべての条件が満たされるようにあらかじめ記述しておく必要があります。
まず、 ここでは上記の条件を満たす main()メソッドのみで、 プログラムが構成されている場合を考えます。

・ main()メソッドが見つかると、その先頭の行から、上から下に向けて 順番に命令が呼ばれていきます。 特別な指定がない限り、メソッドの中の処理は「上から下へ」が大原則です。
したがって、まず最初の行の命令が実行され、"1st message" が表示されます。 次に、その直後の行命令が実行され、"2nd message" が表示されます。
さて、その次に実行されるのはどんな仕事でしょうか? プログラムの次の行から、「条件分岐」の制御構造が登場します。 ここでは if で始まる条件分岐の判定式の値によって メッセージ表示の処理が選択されます。 ( )の中に記述された式が成り立つか否か(値はbloolean型の true か false いずれかの 値になります)で判定され、成り立てば if の後のブロック内の処理が、 成り立たなければ else の後のブロック内の処理が選択されます。 メッセージの表示の処理は2つのうちのどちらかしか実行されない点に注意してください。
条件分岐から抜けた後に、もう1行最後の行の命令があります。 最後にこの命令が実行され、"last message" と表示されます。 main()メソッドの最後の行が実行し終わると、 もうその先には処理すべき行がありません。 この時点でプログラムは終了します。
(Javaでは複数の処理を並列して実行する「マルチスレッド」を採用しているため、 main()メソッドの最後の命令が終了しても、それがプログラムの終了であるとは 限りません。しかし、説明を簡単にするため、しばらくは「マルチスレッド」の ことは考えないことにします。)

・ 今度はループ(繰り返し)の制御構造について説明しましょう。 while文の直後の () の中の記述は if文の時と似ています。 ここでは、ブロックの処理を実行するかどうかの判定条件として利用されます。 判定条件が成り立っていれば、続くブロックの一連の処理が実行されます。 ブロック内の処理は上から下へ実行されていきますが、 ブロックの最後まで来ると、 whileの文に戻り、再び条件式をチェックします。 この判定式が成り立っている間は、ブロックの処理が再び繰り返されます。
条件式が成り立たなくなると、繰り返しは行われず、ループのブロックの 後に来る次の処理に移ります。 以下のサンプルの実行をたどってみましょう。


public class FlowTest2 {
    public static void main( String[] args ) {
        System.out.println( "before the loop" );
        int i = 0;
        while( i < 10 ) {
            System.out.println( "in the loop" );
            i++;
        }
        System.out.println( "after the loop" );
    }
}

まず、main()メソッドの最初の行が実行されます。"before the loop" の メッセージが表示されます。 次にint型の整数の i が宣言され、その初期値に0が代入されています。 そして while文によるループの制御構造に入ります。 iの値が10と比較されていますが、この時点では条件式は成り立っています。 そこでブロックの中の処理が順に実行され、"in the loop" のメッセージを 表示し、iの値を 1だけ増やします。 そして、処理はまた whileの条件式のチェックまで「前に戻り」ます。 この時点でも iの値は 1ですから条件式は成り立ち、再びブロックの処理が 再開されます。 以下、同様のことが繰り返されますが、iの値は回数が繰り返されるたびに増加して、 ある時点で 10に達します。その時点で、条件式は成り立たなくなりますから、 繰り返しはそれ以上は行われません。 ループの制御構造を抜けます。そして、その後にある行の命令が実行されます。 最後に "after the loop"のメッセージが表示されるわけです。

・

・ Javaのプログラムの処理は、 「条件分岐」と「繰り返し」の記述を組み合わせることで実現されます。 それらの対象となる範囲は { } によって囲まれます。こうしたかたまりを 「ブロック」と呼びます。 (処理の対象が単独の命令の場合には、例外的に { } を省略することができます。)
ブロックの内部にさらに別の条件分岐や繰り返しのブロックを記述することが できます。その内部にもさらに、というように何重にでもすることが可能です。 このような構造は「階層構造」と呼ばれます。
このようにブロックの構造にまとめることで、 プログラムの行数が増えてきても、その内容は理解しやすくなります。 たとえば、ブロックの途中から処理が始まることは絶対にありません。 break文などで特別に処理を抜ける場合以外は、ブロックの処理を実行する・しない の区別はすべてブロックの最初にある条件判定の記述から読み取ることができます。 (do-while文のみ判定はブロック後。) そして、より内部の構造の処理が終了しないうちは、処理が外部に移ることは ありません。
多重の構造を持つ繰り返しによって計算量の多い処理も、 非常に単純な記述で実現することが可能となります。 特殊な条件がある場合でも、 条件分岐と組み合わせることで、処理の共通部分を共有することができます。


public class KuKu {

    public static void main( String[] args ) {

        for( int x=1; x<=9; x++ ) {
            for( int y=1; y<=9; y++ ) {
                if( x*y < 10 )
                    System.out.print( " " );
                System.out.print( x*y + " " );
            }
            System.out.println( "" );
        }
    }
}