【連載12】Javaプログラミングの基本 繰り返し(for文)

同じ処理を繰り返し実行させたいということはコンピュータの世界ではよくあることです。

入力したファイルやデータベースから取得した行ごとだったり、配列の要素数分だったり、その利用シーンは様々であり、プログラミングをしていく上でif文同様、よく使っていくことになるでしょう。

Javaで繰り返し処理を行う際に利用する方法のひとつがfor文です。

今回の記事では、そのfor文について解説していきます。

for文の使い方

for文は指定した条件式が真(true)となる間、処理を繰り返します。決まった回数繰り返したいといった場合、条件式で繰り返し回数を指定することになります。

for文の構文は以下のとおりです。

for ( 初期化式; 条件式; 変化式 ){
  // 繰り返しの中で実行される処理
  …
}

for文は初期化式、条件式、変化式から構成されます。

初期化式
繰り返し処理(forループとも呼ばれる)に入る前の最初の値を指定
条件式
繰り返し条件を指定
変化式
繰り返し処理の実行が終わり、次の繰り返しに入る前の後処理を定義

具体的には実際のサンプルを交えて解説します。

public class Sample12_01{
    public static void main(String[] args){
        for (int i = 0; i < 5; i++){
            System.out.println("i=" + i);
        }
    }
}
i=0
i=1
i=2
i=3
i=4

サンプルでは、変数iの値を1加算しながら、その値を画面に出力しています。

どのように動いているのか、for文を分解しながら考えていきましょう。

for (int i = 0; i < 5; i++){
    System.out.println("i=" + i);
}

「int i = 0;」の部分が初期化式になります。初期化式は、for文が実行されると最初の1回だけ実行されます。条件式で使用する変数の初期化に使われるのが一般的です。

このサンプルでは、int型変数「i」を「0」で初期化しています。

次の「i < 5;」が条件式になります。この条件式を満たす(trueとなる)場合は、forループを繰り返します。

このサンプルでは、変数「i」の値が「5より小さい間、繰り返す」と指定しています。

最後の「i++」が変化式になります。forブロック({ }で囲われた範囲)内の処理が終わり、次の繰り返し処理に入る前の後処理を定義します。

このサンプルでは、変数「i」の値を1加算しています。(このように繰り返す回数を格納する変数のことを「カウンタ変数」と言います。)

変数のスコープについて

for文の中で使用した変数のスコープについて意識する必要があります。

変数のスコープとは、変数がアクセスできる範囲(有効範囲)のことです。変数宣言をどこで行ったかによって、スコープが変わってきます。

次のサンプルコードを見てください。

public class Sample12_02{
    public static void main(String[] args){
        for (int i = 0; i < 5; i++){
            System.out.println("i=" + i);
        }
        System.out.println("i=" + i);
    }
}

このサンプルコードをコンパイルしてもエラーとなってしまいます。

Sample12_02.java:6: エラー: シンボルを見つけられません
        System.out.println("i=" + i);
                                  ^
  シンボル:   変数 i
  場所: クラス Sample12_02
エラー1個

これはfor文の外で変数「i」を参照しようとしているためです。

for文の初期化式で変数「i」を宣言しています。この場合、変数「i」のスコープはforブロックの中のみとなります。

変数は、変数を宣言したブロック({ }の間)がその変数を扱える範囲となり、その範囲外で使おうとすると、コンパイルエラーとなります。

もし、forブロックの中で扱った変数をforブロックの外でも扱いたい場合は、以下サンプルのように変数宣言をforブロックの外で行う必要があります。

public class Sample12_03{
    public static void main(String[] args){
        int i;
        for (i = 0; i < 5; i++){
            System.out.println("i=" + i);
        }
        System.out.println("i=" + i);
    }
}
i=0
i=1
i=2
i=3
i=4
i=5

最後の「i=5」の出力がforブロックの外で実行しているSystem.out.printlnの出力結果となります。

複数の初期化式と変化式を指定する

for文で指定する初期化式と変化式は、ひとつだけでなく複数の式を記述することもできます。

複数の式を指定したい場合は、式と式の間をカンマ(,)で区切ります。

for ( 初期化式1, 初期化式2; 条件式; 変化式1, 変化式2 ){
  // 繰り返しの中で実行される処理
  …
}

このようにカンマで区切ることで初期化式と変化式を複数指定することができます。

ただし、条件式についてはカンマ区切りでの複数指定はできない点に注意してください。条件式は、ANDやORなどの論理演算子を使って複雑な式を作成することになります。

初期化式と変化式を複数指定したfor文のサンプルコードを示します。

public class Sample12_04{
    public static void main(String[] args){
        for (int i = 0, j = 4; i < 5; i++, j--){
            System.out.println("i=" + i + ", j=" + j);
        }
    }
}
i=0, j=4
i=1, j=3
i=2, j=2
i=3, j=1
i=4, j=0

初期化式にて、int型変数「i」と「j」を宣言し、初期値の代入も併せて行っています。さらに変化式では、変数「i」をインクリメント、「j」をデクリメントさせています。

あとは、forブロックの中で、それぞれの変数の値を出力させています。

ここで、初期化式についてもう一度着目してください。

for (int i = 0, j = 4; i < 5; i++, j–)

このfor文を、もしかしたら以下のように記述してしまう方もいらっしゃるのではないでしょうか。

for (int i = 0, int j = 4; i < 5; i++, j–)

変数「i」と「j」、それぞれに型を指定するというため、上記のように記述してしまいがちですが、この記述は誤りであり、コンパイルエラーとなります。

では、変数「j」の型は何になるのか、ということですが、正解はint型になります。

それはつまり、「int i = 0, j = 4;」の意味は、int型の変数「i」と「j」の2つを宣言しているという意味になります。

では、異なる型の変数を指定したい場合はどうすれば良いのでしょうか。

その回答ですが、初期化式では異なるデータ型の複数の変数を指定することはできません。

つまり、以下のような記述はできないということです。

for (int i = 0, long j = 4; i < 5; i++, j–)

上記の記述ではコンパイルエラーとなります。

もし、複数の型の変数を初期化式で指定したい場合は、for文の前で変数の宣言を行います。

public class Sample12_05{
    public static void main(String[] args){
        int i;
        long j;
        for ( i = 0, j = 4; i < 5; i++, j--){
            System.out.println("i=" + i + ", j=" + j);
        }
    }
}

サンプルコードでは、整数型を指定していますが、このようにfor文の前に変数を宣言しておけば、小数型や文字型の初期化(初期値の設定)も可能です。

初期化式、条件式、変化式を省略する

初期化式、条件式、変化式を省略することもできます。

どういうことかの説明の前に以下のサンプルコードを見てください。

public class Sample12_06{
    public static void main(String[] args){
        int i = 5;
        for ( ; ; ){
            System.out.println("i=" + i);
            i--;
            if ( i == 0 ){
                break;
            }
        }
    }
}
i=5
i=4
i=3
i=2
i=1

for文の中で初期化式、条件式、変化式をすべて省略しており、それらを区切るセミコロン(;)のみしか記述していません。

条件式がなければ、いつまでもforブロックの中の処理を繰り返してしまいますが、その代わりにif文で繰り返し条件の判定を行っています。その判定で条件を満たせば、break文によってforブロックを抜けて、次の処理に移るという動きとなります。

forブロックの中でbreak文を実行することで、現在の繰り返し処理を強制的に終了し、forブロックを抜けます。

このように、for文の条件式以外でも繰り返し条件の判定をすることができます。

注意点として、初期化式、変化式も省略しているので、for文に入る前に変数初期化を行い、forブロックの中で変化式に相当する処理(上記サンプルでは「i–;」)を必ず記述する必要があります。

もしその記述を忘れると、いつまでも繰り返し処理が終わらない「無限ループ」となってしまいます。

まとめ

for文は条件式の他に、forブロック内で使用する変数の初期化や変化式を記述することができます。

その便利さから、よく使用する構文となりますので、特徴をしっかり押さえておきましょう。