WisdomSoft - for your serial experiences.

3.2 if文

条件に従ってプログラムの流れを分岐させる方法について解説します。

3.2.1 プログラムの分岐

これまでのプログラムの流れは、main() 関数から始まり、ソースの上から下へと忠実に実行されるだけのものでした。しかし、実践プログラムでは、状況に応じて適切な処理を実行できなければなりません。そのためには、プログラムを分岐させる必要があります。プログラムの分岐制御を行う最も簡単な方法は if 文を使うことです。

if 文は最も簡単な流れ制御の命令です。これは「~であれば~する」という動作を実現することができます。Java 言語では、このような流れ制御を行うための判断に boolean 型を使います。boolean 型が true であれば実行し、そうでなければ実行しないように仕掛けるのです。一般的な if 文は次のような構文になります。

if文
if (条件式) 

条件式には boolean 型の値を指定しなければなりません。これが true であれば続く文を実行し、そうでなければ文は無視されます。こうした性質から、多くの場合は if 文の条件に関係演算を使った式などを指定し、その結果から適切なプログラムを実行するような形になるでしょう。

コード1
class Test {
	public static void main(String args[]) {
		if (true) System.out.println("if (true)");
		if (false) System.out.println("if (false)");
	}
}
実行結果
>java Test
if (true)

コード1は if 文の効果を確認するための最も簡単なプログラムです。最初の if 文の条件式には true がリテラルで指定されているため、この if 文に続く文は必ず実行されることが保証されます。次の if 文は false が指定されているため、逆に実行されることはありません。実行結果を見ると、予想通り if (true) の文が実行されていることがわかります。

これで、条件式を与えることによって、状況に応じた適切なコードを実行するように命令できるようになりました。例えば、ある変数の値を調べ、その結果によって処理を変化させることができるでしょう。

コード2
class Test {
	public static void main(String args[]) {
		int iValue = 10000;

		if (iValue < 1000) 
			System.out.println("iValue は 1000 より小さい");
		if (iValue > 1000)
			System.out.println("iValue は 1000 より大きい");
		if (iValue == 1000)
			System.out.println("iValue は 1000 である");
	}
}
実行結果
>java Test
iValue は 1000 より大きい

コード2は、変数 iValue に格納されている値の大きさによって適切な文字列を表示させるようにプログラムされています。ソースでは iValue を 10000 で初期化しているため、上から2番目の if 文の条件に合致し、"iValue は 1000 より大きい" という結果が得られます。iValue の初期値を変更すれば、結果が変化することを確認してください。

3.2.2 if-else 文

if 文は条件が true の時のみ実行される文ですが、条件が false の時に処理を実行したい場合もあるでしょう。一般的な方法では、論理否定演算子 ! を使うか bValue == false という条件式を用いることでこの問題を解決することができます。しかし「~であれば~する。そうでなければ~する」という条件を満たす場合、if 文だけでは難しくなります。

if 文で判定した条件式が true だった場合と、false だった場合、それぞれの結果に分ける場合、2回に分けて if 文を記述するのは冗長であることと、整合性に問題があることが指摘されます。

if (bValue) statement...; //~であれば~する 
if (!bValue) statement...; //そうでなければ~する

これは、間違っていると言うほどのミスではないものの、適切な表現ではありません。このように、1 つの条件に対して true の場合と false の場合、それぞれの結果を用意する場合は if-else という形式の if 文を使います。これは、次のような形になるでしょう。

else付きのif文
if (条件式) 文 else 

else キーワードまではこれまでの if 文と同じです。else キーワードに続く文は、条件が false だった時のみ実行される文となります。つまり、この場合は条件式の評価結果が true の時は else の前にある文が、false の時は else の後にある文が実行されるのです。else キーワードは常に if キーワードに対応しているため、else 文の前には必ず if 文が必要です。else に対応する if 文が見つからない場合はエラーとなるので注意しましょう。

コード3
class Test {
	public static void main(String args[]) {
		if (false) System.out.println("if (true)");
		else System.out.println("if (false)");
	}
}
実行結果
>java Test
if (false)

コード3は、else キーワードを利用して、よりスマートな if 文を実現しています。if の条件式が true の場合の文まではこれまでと同じですが、条件が false だった時に実行する文は else を使って表現しています。結果を見てわかるように、条件式が false であれば else 直後の分が実行されています。

3.2.3 if の入れ子構造

プログラムの世界では、ある命令の中に同一の命令を重ねいれるような処理がしばしば見受けられます。例えば if 文で指定する文にさらに別の if 文を指定するようなことが可能です。このような構造を入れ子と表現します。

if を入れ子にすると、「~であれば~する。そうでなければ~する。そうでなければ~する…」というプログラムの流れを表現することができるようになります。これは、複雑な処理や値の関係を構築する時に実用することができます。コード2は if-else 形式と入れ子をうまく使うことで最適化することができます。

コード4
class Test {
	public static void main(String args[]) {
		int iValue = 1000;

		if (iValue < 1000) 
			System.out.println("iValue は 1000 より小さい");
		else if (iValue > 1000)
			System.out.println("iValue は 1000 より大きい");
		else System.out.println("iValue は 1000 である");

	}
}
実行結果
>java Test
iValue は 1000 である

コード2のように、単純な if の列挙で特定の条件を何度も分析する場合、整合性に問題が発生します。最初の if で条件が合致し、文を実行するまでは良いのですが、実行した文で変数 iValue の値を変更するかもしれないのです。もし、条件に関係する変数に変更が加えられた場合、直後の if で再び条件が合致してしまう可能性があるのです。二者択一の処理を期待した場合、これはバグとなってしまうでしょう。

この問題を回避するには、コード4のように if-else 形式と、if の入れ子を利用するべきです。この場合、何らかの条件に合致すれば、適切な文を実行した後、if-else の構造から抜け出すため、常に 1 つの処理だけか実行されることを保証できるのです。さらに、文を実行した後、不要な条件の評価もしなくなるため、実行速度も向上するでしょう。