新人エンジニア研修で知っておきたい条件分岐の使い方

なぜ、判定条件の理解が重要なのか、その理由。

この記事では、弊社の新人エンジニア研修の参考にJavaを解説します。

前回は演算子について解説しました。

今回は条件分岐と判定条件について解説します。プログラムの特徴として「条件によって処理を変えることができる」というものがあります。その意味からこの章の内容は重要です。

あわせて、前回の演算子の続きで、

・関係演算子(比較演算子とも呼ばれます)
・三項演算子
・論理演算子

についても触れていきます。

1.if文

if文を使い条件に応じて処理をさせたり、させなかったり,といったプログラムが作成できます。

例えば、「もしも、20歳以上なら酒を飲む」といった処理です。

下図4.1の通りです。

条件がtrueの場合のみ処理をするif文
図4.1 条件がtrueの場合のみ処理をするif文

プログラム風に書くと以下の通りです。

if(20歳以上){
 酒を飲む;
}

一般化すると以下のように書けるでしょう。

<構文>

if(条件式){
 命令文;
}

上記の命令文は条件がtrueの場合に実行されます。条件式はboolean型の値、つまり true または false という値を持つものであればなんでもOKです。

 Javaで書くと以下Example01のようになります。

package chap04;

public class Example01 {
    public static void main(String[] args) {
        int age = 20;
        if (age >= 20) {
            System.out.println("酒を飲む");
        }
    }
}

このプログラムを実行すると条件式の値はtrueのため標準出力には「酒を飲む」と出力されます。条件式の値がfalseの場合(例えば、age = 19)は何も出力されません。この時の、「>=」記号を関係演算子と呼びます。

関係演算子とは、2つの式や値の比較を行い、結果を真偽値で返すもののことをいいます

関係演算子の解釈で新入社員の皆さんにアドバイスできることとしては、あまり長々と考え込まないことです。true or false の判断さえできれば大丈夫です。

例えば、

age >= 20

という式も長々と見ているとだんだん意味がぼやけてしまうからです。(ゲシュタルト崩壊

実際に変数に値を入れて、

20 >= 20

をtrueと判断できれば大丈夫です。

2.関係演算子

ここで、Javaの判定条件を構成する関係演算子をまとめましょう。

 Javaで書くと以下Example02のようになります。

package chap04;

public class Example02 {
    public static void main(String[] args) {
        System.out.println(1 == 1);
        System.out.println(1 != 2);
        System.out.println(1 > 2);
        System.out.println(1 < 2);
        System.out.println(1 >= 2);
        System.out.println(1 <= 2);
    }
}

<結果は下記の表の右端列>

関係演算子読み方説明式の例結果(値)
==イコールイコール左辺と右辺が等しい1 == 1true
!=びっくりイコール左辺と右辺が等しくない1 != 2true
>大なり左辺が右辺より大きい1 > 2false
<小なり左辺が右辺より小さい1 < 2true
>=大なりイコール左辺が右辺以上である1 >= 2false
<=小なりイコール左辺が右辺以下である1 <= 2true
instanceof ※後述インスタンスオブ左辺が右辺のクラスまたはそのサブクラスのインスタンスであるInteger i = 1; 
i instanceof Number;
true
表4.1 関係演算子

前回解説したように=が一つは代入の意味でした。そのためJavaで等しいを表現するには「==」と=を2つ重ねます。ここは新人エンジニア研修で間違えられやすいところです。

また、「より大きい(超過)」と「以上」、「より小さい(未満)」と「以下」も厳密に使い分ける必要があります。 

練習問題をやってみましょう。

問題解答変数aの値が19である時
1.変数aの値が20であるa == 20false
2.変数aの値が20でない
3.変数aの値が20より大きい
4.変数aの値が20より小さい
5.変数aの値が20以上である
6.変数aの値が20以下である
表4.2 関係演算子の問題

なお、 命令文が1つだけの場合は{}を省略することも可能です。

以下のプログラムは上記Example01と同じ結果になります。

package chap04;

public class Example03 {
    public static void main(String[] args) {
        int age = 20;
        if (age >= 20) 
            System.out.println("酒を飲む");
    }
}

<実行結果>

酒を飲む

ただし、うっかりすると以下のように条件に応じた処理の範囲を間違えることもあります。未成年に対しては酒も煙草も禁じるつもりで以下のように書くと意図しない結果になります。

package chap04;

public class Example04 {
    public static void main(String[] args) {
        int age = 19;
        if (age >= 20) 
            System.out.println("酒を飲む");
            System.out.println("煙草も吸う");
    }
}

<実行結果>

煙草も吸う

したがって、一文の処理であっても{}で囲むことは良い習慣です。

ただし、他人(特にベテラン)の書いたコードは{}で囲まれていないことも想定してください。

3.if else文

例えば、「もしも、20歳以上なら酒を飲む、そうでなければジュースを飲む」といった表示をさせたい場合はどうすればいいでしょうか?

 以下Example05のようなif文を連続させたプログラムを考えたとします。

package chap04;

public class Example05 {
    public static void main(String[] args) {
        int age = 20;
        if (age >= 20) {
            System.out.println("酒を飲む");
        }
        if (age < 20) {
            System.out.println("ジュースを飲む");
        }
    }
}

確かに、これでも実現できます。しかし、ifの条件判断を2回実行してしまっています。20歳以上であれば、20歳未満かどうかという判断は不要ですね。無駄な動きをしないプログラムを作ることも大切なことです。

なお、デバッガの機能を使うと以下のようにプログラムの動きを可視化できますので、講師から方法をお聞きください。

新人エンジニア研修

今回の条件分岐を図示すると以下の通りです。

条件がfalseの場合にも処理をするif文
図4.2 条件がfalseの場合にも処理をするif文

このような多分岐構造にはif else文が使えます

if(20歳以上){
 酒を飲む;
} else {
 ジュースを飲む;
}

Javaで書くと以下Example06のようになります。

package chap04;

public class Example06 {
    public static void main(String[] args) {
        int age = 19;
        if (age >= 20) {
            System.out.println("酒を飲む");
        } else {
            System.out.println("ジュースを飲む");
        }
    }
}

<実行結果>

ジュースを飲む

実行すると条件式の値はfalseのため標準出力には「ジュースを飲む」と出力されます。では、さらに細かく条件ごとの処理に分岐させたい場合はどうしたらよいでしょうか?

以下のように  if~else文を連結することができます。

なお、“elseif”ではなく、“else if”のようにifとelseの間にはスペースが入ります。(elseifと書く言語を学んだことのある方は気をつけましょう)

点数【score】によってA、B、C、Dの4段階評価を行います。

package chap04;

public class Example07 {
	public static void main(String[] args) {
		int score = 88;
		if (score >= 90) {
			System.out.println("A");
		} else if (score >= 80) {
			System.out.println("B");
		} else if (score >= 70) {
			System.out.println("C");
		} else {
			System.out.println("D");
		}
	}
}

<実行結果>

B

ただし、条件が多くなると記述が複雑になってしまうのがif else文の欠点です。そんな時には次のswitch文の利用を検討してみましょう。

4.switch文

switch文はアルゴリズムでいう多岐分岐を扱う文です。

文法は以下の通りです。

<構文>

switch (式) {
   case 値A: // 式の値が値Aだったときの処理 break;
   case 値B: // 式の値が値Bだったときの処理 break;
   default: // 式の値がいずれのcaseの値とも一致しなかったときの処理
}

switch文の値で使える型は、char、byte、short、int、String、enum(後述)があります。default句は値がどのcaseの値とも一致しなかった場合の処理を記述するためにあります。

このswitch文もIDEのコードテンプレートによって簡単にひな形を挿入する方法があります。講師から聞いてください。

以下のExample08は100点満点のテストの点数によってABCDの4段階評価をするプログラムです。

package chap04;

public class Example08 {
	public static void main(String[] args) {
		int score = 88;
		switch (score / 10) {
		case 7:
			System.out.println("C");
			break;
		case 8:
			System.out.println("B");
			break;
		case 9:
		case 10:
			System.out.println("A");
			break;
		default:
			System.out.println("D");
		}
	}
}

<実行結果>

B

スイッチの状態にはオンとオフしかなく、中間はありません。同様にswitch文は何かの間を表現することはできません。例えば、「60以上70未満」の場合、といった表現には上記のような工夫が必要になってしまいます。そのような場合はif文を使うほうが良いでしょう。

なお、break句が使用されない場合、一致するケースの後のすべてのswitch文が終わりまで順番に実行され意図しない結果になることがあります。フォールスルー【fall through:素通し】といいます。バグの温床になり得ますから、あえてフォールスルーさせるとき以外は気をつけてください。

package chap04;

public class Example09 {
	public static void main(String[] args) {
		int score = 88;
		switch (score / 10) {
		case 7:
			System.out.println("C");
		case 8:
			System.out.println("B");
		case 9:
		case 10:
			System.out.println("A");
		default:
			System.out.println("D");
		}
	}
}
実行結果の予想:

5.三項演算子

ここでは、少し応用的なテーマとして三項演算子を紹介します。三項演算子を使うと一文で簡潔に分岐構造を表現できます。以下はイメージです。

三項演算子の見方
図4.3 三項演算子の見方

三項演算子の基本構文は以下の通りです。

<構文>

条件式 ? 真の場合の値 : 偽の場合の値;

条件式がtrueの場合、式全体の値は「真の場合の式」の評価結果になります。falseの場合は「偽の場合の式」の評価結果になります。これらの式の位置には、単純な値だけでなく、関数の呼び出しを含む任意の式を使用することができます。この柔軟性により、三項演算子はif文に比べてコンパクトな条件付き代入や評価を行うことができますが、複雑な処理には向かない場合があるため、使い所を選ぶ必要があります。

以下のExample10で見てみましょう。

package chap04;

public class Example10 {
	public static void main(String[] args) {
		char c = 'y';

		String result;
		result = (c == 'y') ? "Yes" : "No";//文法上()は不要ですが、見やすさのために書いています。


		System.out.println(result);
	}
}

<実行結果>

Yes

ただし、三項演算子を多用することには可読性を低下させるという批判もあります。極端に複雑な入れ子構造を使用したりはしないようにしましょう。

また、自分は三項演算子は使わない、という人も他人の書いたソースを読む必要がありますから読めるようにはしておきましょう。

6.論理演算子

論理演算子を使うと複数の条件を組み合わせて複雑な条件式を作ることができます

論理演算子は次の4種類です。

論理演算子読み方式がtrueになる条件使用例
&&かつ AND左辺と右辺の両方がtruegender == 'F' && age >= 16
||または ORすくなくとも左辺と右辺のどちらかがtruegender == 'F' || age >= 16
!否定 NOT条件式がfalse!(gender == 'F' )
^XOR(エクスオアー)左辺と右辺のどちらかがtrueで他方がfalsegender == 'F' ^ age >= 16
表4.3 論理演算子

新人エンジニア研修ではxorは結構ですので、まずは、ANDORNOTを押さえましょう。

以下のExample11で見てみましょう。

package chap04;

public class Example11 {
    public static void main(String[] args) {
        System.out.println(true && true);
        System.out.println(true && false);
        System.out.println(true || false);
        System.out.println(!true);
        System.out.println(!false);
    }
}

<実行結果>

true
false
true
false
true

例えば、学生の成績を付けるプログラムを考えます。英語【English】と数学【Math】それぞれ100点満点のテストで評価はS,A,B,Cの4段階評価とします。

英語と数学の両方が80点以上だったらS評価。

どちらか一方が80点以上だったらA評価。

どちらか一方が70点以上だったらB評価。

それ以外はC評価とします。

package chap04;

public class Example12 {
    public static void main(String[] args) {
        int english = 80;
        int math = 75;
        if (english >= 80 && math >= 80) {
            System.out.println("S");
        } else if (english >= 80 || math >= 80) {
            System.out.println("A");
        } else if (english >= 70 || math >= 70) {
            System.out.println("B");
        } else {
            System.out.println("C");
        }
    }
}
実行結果の予想:

論理演算子なしで同じコードを書こうとしたら大変です。

7.演算子の優先順位

主要な演算子が出そろったところでその優先順位についてまとめます。

算術演算子 > 関係演算子 > 論理演算子

の順に優先されます。

まず、算術演算子は関係演算子より優先されます。

例えば、

1 + 1 > 2 - 1

という式は以下のように解釈されます。

(1 + 1) > (2 - 1)

※()内が優先される

また、関係演算子は論理演算子より優先されます。

1 == 1 && 2 >= 1

という式は以下のように解釈されます。

(1 == 1) && (2 >= 1)

また、論理積は論理和よりも優先されますが、カッコを使うことで論理和を優先させることができるということは、数学の類推で理解可能だと思います。

a > 10 && b < 5 || c == 0
a > 10 && (b < 5 || c == 0)

さらに論理を否定した場合についても整理しておきます。

例えば、

a + 1 > b -10

という式の否定を単純に書けば、以下のようになります。

!(a + 1 > b -10)

また、カッコを開いて以下のように書くこともできます。

a + 1 <= b -10

すなわち、否定は、不等号の向きを逆にして、イコールがなければ付ける、イコールがあれば取り去る、で大丈夫です。

また、論理演算子の否定の場合は「&&は||」に、「||は&&」に変換します。

つまり、

!(gender == 'F' && age >= 16)

という式は以下のように解釈されます。

gender != 'F' || age < 16

いずれにせよ、わかり易い表現を採用しましょう。

簡単な練習問題をやってみましょう。

問題解答a = 19 , b = 1のとき
1.変数aの値が20である かつ 変数bの値が1である。a == 20 && b ==1false
2.変数aの値が20である または 変数bの値が1である。
3.上記1の否定(括弧なし)
4.上記2の否定(括弧なし)
表4.4 論理演算子の問題

気をつけないといけないのは、日本語で「aまたはbでない」と言った時に2つの意味がありえることです。

!(a or b)
か、それとも
a or !b
かです。

否定の“ない”がどこに掛かっているのかを確認する必要があるのです。

<まとめ:隣の人に正しく説明できたらチェックを付けましょう>

□ if文を使い条件に応じて処理をさせたり、させなかったりといった処理ができる

□ 関係演算子とは、2つの式や値の比較を行い、結果を真偽値(true or false)で返すもののことをいう

□ 多分岐構造にはif else文やswitch文が使える

□ 三項演算子を使うと一文で簡潔に分岐構造を表現できる

□論理演算子を使うと複数の条件を組み合わせて複雑な条件式を作ることができる

まとめができたら、アウトプットとして演習問題にチャレンジしましょう。

以上、今回は「条件分岐で場合に応じた処理ができるようになる」方法について見てきました。

次回は、「繰り返しで単純作業をコンピュータに任せる」方法を学びます。

条件分岐で場合に応じた処理ができるようになる 最後までお読みいただきありがとうございます。