Javaのプログラムの「制御構造」を理解しよういまから始めるJava(6)

» 2003年06月18日 00時00分 公開
[平井玄@IT]

 前回「メソッドとコンストラクタはなぜ必要?」では、メソッドとコンストラクタの説明を通して、プログラムに制御構造が必要な理由を説明しました。今回は具体的に制御文を取り上げて、プログラムの制御構造を理解します。

制御構造とは?

 現在、私たちが日常的に使っているコンピュータには、CPUが解釈できる命令(掛け算、足し算など)と、データ(掛ける数、足す数など)が一緒になってメモリに蓄えられているという特徴があります。命令とデータがどのような形式でメモリ内に蓄えられているかはCPUによって異なります。

 CPUは設計時に、はじめにメモリのどの位置から読み出すのかが決まっています。CPUは電源投入後、決められた位置からコードを読み出し、読み出した順番に解釈して実行していくわけです。CPUは、メモリから読み出した命令を解釈して実行するという処理を電源が落とされるまで続けます。

 前回も説明しましたが、CPUの動作は人間をまねたものです。紙テープに書かれた命令とデータを順番に読み込みながら計算するのがコンピュータの基本機能です。しかし、ただ順番に実行するだけでは複雑な処理はできません。同じことを何度も繰り返したり、条件によって処理の内容を切り替える必要が出てきます。

 プログラミング言語の多くには、プログラムを最初から単に「順序どおりに実行」する以外に、2つの処理方法が用意されています。1つは「繰り返し」です。ちょうどテープを巻き戻して再生するように、CPUが次に読み出すメモリの位置を指定します。もう1つは「条件分岐」です。ある条件を指定して、条件に適合していれば処理を続行するようにします。条件に適合しない場合は、ちょうどテープを早送りするように、CPUが次に読み出すメモリの位置を指定します。

 Javaのようなプログラミング言語では、実際にメモリの位置を指定することはありません。しかし、Javaにもプログラムを実行する順序を制御するための文が用意されています。また、Javaをはじめとする多くのプログラミング言語は、「順序どおり実行する」「繰り返して実行する」「条件を判断して実行する」のいずれかの構造でプログラムを記述します。こうした構造を「制御構造」といい、制御構造を記述するための文のことを「制御文」と呼びます。Javaで使われる主な制御文は以下のとおりです。

if、if〜else

 ifは最も頻繁に使う制御文です。制御構造のうち、主に条件分岐を応用したものといえるでしょう。

   ifの例1
public class ifsample {
  public static void main( String args[] ) {
    int a = 1;
    if ( a == 1 )
      System.out.println("変数aは1です");
      
      System.out.println("ここは変数aとは関係なく実行される");
  }
}

 ifは「if(条件式)」の形式で条件を調べて、条件に合致(式を評価した結果がtrueであるとき)だけその次の文を実行します。条件がtrueでないときは、ちょうどテープを早送りするように、次の次の文を実行します。条件式で使われている「==」という演算子にも注目しましょう。「==」は比較の演算子で、この場合は「aが1であるかどうか」という意味です。

 条件がtrueのとき、2つ以上の文を実行したいときは「{」〜「}」で囲んでブロックにします。

   ifの例2
public class ifsamplewithblock {
  public static void main( String args[] ) {
    int a = 1;
    if ( a == 1 ) {
      System.out.println("変数aは1です");
      System.out.println("もう一度いいます、変数aは1です");
    }
    System.out.println("ここは変数aとは関係なく実行される");
  }
}

 if文では、条件がtrueのときだけでなく、条件がfalseだったときに実行する文も書けます。

   if〜elseの例
public class ifelsesample {
  public static void main( String args[] ) {
    int a = 1;
    if ( a == 1 )
      System.out.println("変数aは1です");
    else
      System.out.println("変数aは1ではありません");

    System.out.println("ここは変数aとは関係なく実行される");
  }
}

switch

 switchもよく使われる制御文です。ifと同様の条件分岐ですが、条件式はchar、byte、short、intとして評価されなければなりません。ifとは異なり、分岐先として3つ以上の文を指定できます。

   switchの例
public class switchsample {
  public static void main( String args[] ) {
    int a = 1;
    switch (a)    {
      case 1:
        System.out.println("変数aは1です");
        break;
      case 2:
        System.out.println("変数aは2です");
        break;
      default:
        System.out.println("変数aは1でも2でもありません");
        break;
    }
    System.out.println("ここは変数aとは関係なく実行される");
  }
}

 switchは「switch(条件式)」の形式で式を評価し、式の値ごとにそれぞれの処理を実行するものです。広い意味では条件分岐ですが、「分岐」というよりも「選択」といった方が的確です。それぞれの処理は「case値」以下に記述します。どのcaseにも当てはまらない場合は「default」以下の文が実行されます。上記の例にある「break」にも注目しましょう。breakは「現在の制御構造から抜け出せ」という意味の制御文です。この例の場合、switch(a){〜}のブロックから抜け出します。つまり、switch文全体ではまず条件式が評価され、テープを早送りするように、式ごとの処理が実行され、breakによってswitch文のブロックの外側に制御が移るという順番で処理されます。

for

 forもよく使われる制御文です。ifやswitchとは異なり、条件分岐と繰り返しを組み合わせた制御文です。

   forの例
public class forsample {
  public static void main( String args[] ) {
    int i = 1;
    for ( i = 1; i <= 10; i++ )
      System.out.println(i);
    System.out.println("ここはfor文の外側");
  }
}

 forは「for(式1;条件;式2) 処理」の形式です。処理に先立ってまず式1を実行し、条件がtrueであるとき処理を実行し、さらに式2を実行します。上記の例では、まず変数iに1が代入され、次に1が10以下かどうかを評価し、変数iの値を画面に表示します。次にiの値を1つ加算し、もう一度iが10以下かどうかを評価し、変数iの値を画面に表示します。この処理をiが10以下の間繰り返します。つまり画面には1から10までの数字が表示されるわけです。

 ちょっと抽象的で分かりにくいので、forを使ったほかの例を示しましょう。例えばfor文を使うと、データベースのテーブルを先頭から末尾までレコードの内容を順に読んでいくような処理を記述できます。

for ( table.first(); ! table.eof; table.next() ) {
  table.edit()
  …
}

 つまり、for文はある処理に先立って何かを準備し、条件がtrueの間処理を繰り返す、という制御構造を記述するものです。コンピュータの処理にはこういうものが非常に多いです。例えば、「新着メッセージの一覧を取得し、接続している間、メッセージを順にダウンロードする」という処理もfor文を使って記述できます。

while

 if、switch、forほどではありませんが、よく使われる制御文です。for文同様、条件分岐と繰り返しを組み合わせた制御文です。

   whileの例
public class whilesample {
  public static void main( String args[] ) {
    int a = 0;
    while ( a < 100 ) {
        System.out.println("変数aは"+a+"です");
        a++;
    }
  }
}

 whileは「while(条件式)処理」の形式です。条件式がtrueの間、処理が実行されます。従って、通常は処理の中でwhile文の条件式がfalseになるようにしたり、繰り返しを中断するような文を記述します。そうでないとwhile文は処理を永遠にし続けてしまうからです。つまりwhileはfor文のように処理に先立って何かを準備する必要がない場合に使えばよいわけです。

do〜while

 それほど頻繁に使われるわけではありませんが、上手に使うとプログラムが格段に読みやすくなることがある制御文です。while同様、条件に合致する間、処理を繰り返します。ただし、whileが条件を調べてから処理を実行するのに対し、do〜whileは処理を実行してから条件を調べます。

   do〜whileの例
public class dowhilesample {
  public static void main( String args[] ) {
    int a = 0;
    do {
        System.out.println("変数aは"+a+"です");
        a++;
    } while ( a < 100 );
  }
}

 do〜whileは「do{処理}while(条件式)」の形式です。処理を実行してから条件式を評価します。上記の例とwhile文の例では処理の内容は同じですが、条件式を評価するタイミングが異なります。while文の場合、条件式がtrueのときだけwhile文の内側にある処理が実行されます。それに対し、do〜whileの場合、条件式を評価する前に一度はdo〜while文の内側にある処理が実行されます。

break、continue、return

 制御文には、上記のほかにbreak、continue、returnという文もあります。

 breakについてはswitch文の説明で紹介したとおり、「現在の制御構造から抜け出せ」という意味の制御文です。switch文だけでなく、for、while、do〜whileという繰り返し制御文の中でも使えます。この場合は「繰り返しを中断せよ」という意味になります。テープの例え話でいえば、「リピート再生を中止して次の曲を再生せよ」ということです。

 次の例では、for文の条件式ではiが1000未満の間、変数iの値が繰り返し表示されるはずですが、if文とbreakにより、iは1までしか表示されません。

int i;
for ( i = 0; i < 1000; i++ ) {
  System.out.println(i);
  if ( i == 1 ) break;
}

 continueはfor、while、do〜whileという繰り返し制御文の中で使うことで、「繰り返し処理の先頭位置に制御を戻せ」という意味になります。

 次の例では、for文の条件式ではiが1000未満の間、変数iの値として0から999までが繰り返し表示されるはずですが、if文とcontinueにより、iが奇数のときにしか表示されません。

int i;
for ( i = 0; i < 1000; i++ ) {
  if ( (i % 2) == 0 ) continue;
  System.out.println(i);
}

 returnは前回説明したメソッドの処理を途中で終了するための制御文です。あるメソッドを呼び出した親メソッドに制御を戻すときに使います。

   returnの例
public class returnsample {
  public static void main( String args[] ) {
    int i;
    for ( i = 1; i <= 10; i++ ) {
      System.out.println("変数iは"+i+"です");
      if ( i == 5 )
        return;
    }
    System.out.println("ここはfor文の外側");
  }
}

 上記の例ではfor文の条件式はiが10以下のときにtrueになりますが、for文内のif文により、iが5のときに親メソッドに制御が戻ります。この場合、mainはプログラムの大木になるメソッドですので、プログラムそのものの実行が中断されます。つまり、「ここはfor文の外側」は表示されません。


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。