繰返しと例外処理

前回は,if〜else構文を用いた条件分岐の処理について学びました.条件分岐によって,単に一つ一つの文を順番に実行するだけでなく,ある条件によって処理の流れを変えることができるようになりました.今回は,さらに一歩進んで繰返しの処理を学ぶことにします.たとえば同じ処理を何度も行なう場合などは,繰返しを使うことによって,まとめて書くことができるようになります.さらには,より複雑な処理を実行したり,本格的な計算を行なったりすることもできるようになります.

for文による繰返しの処理

まずは,具体的な例から見ていくことにしましょう.前回,プログラムの入力についても学びました.そこで紹介したHelloCUIプログラムでは,文字列を配列の要素に繰返し入力しながら,最後にその中身を出力するというものでした.ここではそのプログラムを,繰返しを使って書き直してみることにします.

import java.util.ArrayList; // java が提供しているライブラリ、リスト。
import java.util.Scanner;   // java が提供しているライブラリ、スキャナ。 

public class HelloCUI2 {
    public static void main(String[] args) {
        System.out.println("ここに5つの要素(テキスト)が入るリストがあります。");
        System.out.println("何か文字列を入力していってみてください。");
        Scanner scanner = new Scanner(System.in);
        ArrayList<String> list = new ArrayList<String>(); // String が入るリストです。
        for (int i = 1; i <= 5; i++) {
            System.out.printf("%dつ目>", i);
            list.add(scanner.nextLine());
        }
        System.out.print("リストには以下の5つの要素が挿入されました。");
        System.out.println(list.toString());
    }
}

前と違っている部分は,文字列の入力処理の部分をfor文を使ってまとめている部分です.
for文の基本構文は以下のようになっています.

for (初期化コード ; 条件判定式 ; 更新コード) 文

for文の実行が開始されると,まず初期化コードが実行されます.先ほどの例では,初期化コードの部分はint i = 1であり,整数型の変数iを宣言し,それを1で初期化しています.つぎに,条件判定式が評価されます.この判定式が真ならば,for文の中の文が実行され,偽ならば繰返しを終了(for文を抜けるといいます)します.上の例でいうと,初回はi=1なので,条件式i<=5が真なので,for文の中身である{と}で囲まれたブロック文が実行されることになります.for文の中の文の実行が完了すると,つぎに更新コードが実行されます.上の例ではi++の部分になります.i++の意味は「iの値を1つだけ増やしなさい」ということです.したがって,この文を実行するとiの値は2になります.そして,再び条件判定式が評価されます.相変わらずi<=5が成立します(ある条件式を評価した結果が真になることを,成立する,と言うこともあります)ので,再びforの中のブロック文が実行されます.そして,更新コードが実行sあれ,条件判定式が評価され...,といったことをiの値が1,2,3,4,...と増えながら繰り返されることになります.さて,iの値が6になると何が起こるのでしょうか?i <= 5という条件式が成立しなくなるので,for文の実行を終了します.そして,その後の処理である,System.out.print("リストには...に実行が移ります.以上がfor文の処理の流れになります.

さて,さきほどのHelloCUI2では,実はもう1つ変更した部分がありました.以下の部分です.

    System.out.printf("%dつ目>", i);

printfはフォーマット付きの出力を行なうメソッドです.%dは整数の値を十進数(dはdecimalのdです)の書式で出力するように指定する記述子です.ここでは,printfメソッドの2つ目の引数であるiの値を十進数で出力します.
# ここで出てきた「メソッド」や「引数」といった用語はそのうち回を改めてきちっと説明する予定です.

繰返しの回数を変えてみる

さて,先ほどのプログラムは繰返しの回数が5回と決まっていました.これでは面白くないので,"END"という文字列が入力されるまで,ひたすら繰り返すようにプログラムを改造してみましょう.

import java.util.ArrayList; // java が提供しているライブラリ、リスト。
import java.util.Scanner;   // java が提供しているライブラリ、スキャナ。 

//
// ENDという入力があるまで,リストに対して文字列の入力を繰り返す
//
public class HelloCUI3 {
    public static void main(String[] args) {
        System.out.println("ここに要素(テキスト)が入るリストがあります。");
        System.out.println("何か文字列を入力していってみてください。");
        System.out.println("ENDと入力するとプログラムは終了します。");

        Scanner scanner = new Scanner(System.in);
        ArrayList<String> list = new ArrayList<String>();
        for (int i = 1; /* 条件式が空になっている */ ; i++) {
            System.out.printf("%dつ目>", i);
            String line = scanner.nextLine();
            if (line.equals("END")) {
                break;
            }
            list.add(line);
        }
        System.out.printf("リストには以下の%dつの要素が挿入されました。", list.size());
        System.out.println(list.toString());
    }
}

重要な部分は,まずfor文の条件式の中が空っぽ(コメントのみ)になっているところです.for文の条件式は省略することができ,その場合,常に条件式が成立するとみなされます.すなわち,for文の中がいつまでも繰り返されることになります.つぎに,for文を抜けるための条件文が文字列の入力の後に追加しました.以下の部分です.

String line = scanner.nextLine();
if (line.equals("END")) {
    break;
}

まず,入力した文字列をいったんlineという変数に代入しておきます.lineに対してequalsという文字列が等しいかどうかを判定するメソッドを呼び出しています.もし,lineに代入された文字列がENDだったら,line.equals("END")は真になり,if文が成立します.そしてif文の中のbreak文が実行されることになります.break文が実行されると,現在の繰返しを抜け出します.
ここで,if (line == "END") {としていないことに注意して下さい.こうしてしまうと,たとえENDという文字列が入力されてもif文は成立しません.したがって永久にループから抜けられなくなります.(無限ループといいます)
# プログラムが万が一無限ループに陥ってしまって終了させることができなくなった場合,慌てず騒がずCtrl+Cを押しましょう.強制的にプログラムを終了させることができます.

line == "END"が真にならない理由は,オブジェクトの等価性について学ぶと理解できるようになります.簡単に説明すると,line == "END"の場合,lineという文字列オブジェクトと"END"という文字列オブジェクトが同一のオブジェクトである場合に真になります.一方,line.equals("END")の場合,文字列オブジェクトの中身(すなわち文字列)が"END"と等しい場合に真になります.この違いは,同一のオブジェクトとは何かという話にもつながってきます.100円玉を例に取ると分かり易いかもしれません.2つの100円玉があったとします.これらは,異なるオブジェクト(この100円玉とあの100円玉は違いますよね)です.でも100円という価値(中身)は同じです.同じオブジェクト(100円玉)かどうかを判定するのが==であり,同じ中身かどうかを判定するのがequalsであるといえます.