Javaプログラミング基礎

講義資料

if 文

今回の主なテーマは条件判定です。 これはプログラムの実行の途中で、 変数の値を比較し判断することでプログラムの動作を決めることができるものです。 条件判定がないと、プログラムは決められたことを順番に行うことしかできないため、 意味のある仕事をするのは難しいわけですが、 条件判定があると、だいぶ複雑な処理を記述することができるようになります。

教科書 pp.42-43 も同時に参照してください。

条件判定を行う基本的な方法が if 文です。 if 文には 2 つの形式があります。 第 1 の形式は次のとおりです。

if ( 条件式 )
    文

また、第 2 の形式は次のとおりです。

if ( 条件式 )
    文
else
    文

「条件式」の部分には式を書きます。 ここでの式とは、比較を行って真偽を判定するような式です。

if 文の第 2 の形式は次のような動作をします。 最初に条件式を計算して、その結果を求めます。 条件が成立すれば if の次の文を実行し、 成立しなければ else の次の文を実行します。

たとえば、

if (x == y) 
    System.out.println("x is equal to y.");
else
    System.out.println("x is not equal to y.");

という if 文は、最初に x == y の計算を行います。 この条件式は、 xy を比較して、 等しければ条件が成立したとし、 等しくなければ条件が成立しなかったとします。

xy が等しければ、 if の後の最初 System.out.println が実行され、 x is equal to y. と表示することになります。

一方、xy が等くなければ、 else の前の文は実行せず、 else の後の System.out.println だけを実行します。 結果として、x is not equal to y. と表示することになります。

第 1 の形式の動作も、第 2 の形式とほぼ同じです。 最初に条件式を計算して、その結果 (成立、不成立) を求めます。 次に成立した場合に限り、その次の文を実行します。 成立しない場合は文は実行せず、そのままで終わりとします。 つまり、条件が成立しなかった場合に、 何もしないことだけが第 2 の形式との違いです。

if (x > 0)
    System.out.println("x is positive.");

この条件式は、x の値が 0 よりも大きい、 つまり正の数なら条件が成立、そうでなければ条件が成立しないとしています。 正の数であれば、次の System.out.println を実行し、x is positive. と表示します。 0または負の数であれば、何も表示しません。

文について

if 文の形式を説明する際に「文」という言葉を用いましたが、 ここで文について正確に説明する必要があります。

これまで、 プログラムの中に書いた代入や、System.out.println などが上から順に実行されると学んできました。 これらの代入や System.out.println などを 「文」と呼びます。 また、セミコロンも文の一部です (文のあとに何かおまけの記号が付いていると考えてはいけません) 。

if 文の中には、 1 つの文しか書くことができません。 複数の文を書きたい場合、 複数の文を並べたものをグループとして 1 つにまとめ、 全体を 1 つの文のように扱う方法が用意されています。 これを複合文、またはブロックと呼びます。 書き方は次のとおりです。

{
    文
    文
    ...
    ...
    文
}

if 文の中で複数の文を書きたい場合、たとえば、

if (x > 0) {
    y = x;
    System.out.println("x is positive.");
}

のように、ブロックを用いて書くことができます。

二重のif文

教科書p.45を参照してください。

if文の中に書くことができるものは「文」であり、 またif文自体も「文」の一種です。 したがって、if文を二重に書くことができます。

if (x > 0)                      // x > 0 が成立するなら
    if (x % 2 == 0) 
        System.out.println("正の偶数");
    else
        System.out.println("正の奇数");
else                               // x > 0 が成立しないなら
    if (x % 2 == 0) 
        System.out.println("0または負の偶数");
    else
        System.out.println("負の奇数");

比較演算子

教科書 pp.26-27 を参照してください。

if 文の形式の中の「条件式」と書いた部分には、 条件が成立するか成立しないか判定するような式を書きます。 判定式は、yes か no か、成功か失敗か、正しいか正しくないか、 というように 2 つに 1 つの結論を出すような式です。

Java では、条件が成立したかどうかを示すために、 成立した場合を「真 (true)」、成立しなかった場合を「偽 (false)」 という表し方をします。

演算子 意味
== 等しければ true、等しくなければ false
!= 等しくなければ true、等しければ false
< 小さければ true、そうでなければ false
<= 小さいまたは等しければ true、そうでなければ false
> 大きければ true、そうでなければ false
>= 大きいまたは等しければ true、そうでなければ false

これらの演算子は、その左右に書いた式の値を比較して true か false の結果を出します。

特に、代入の = と、比較の == の使い間違いに注意が必要です。 数学の世界ではイコールは、2 つの値が等しいという意味で使われますが、 Java の世界では、= は代入で、 2 つの値が等しいことを示すには == を使う必要があります。

いくつか例を示します。

x == 0
x + y > 3 * z

2 つめの例は、x + y3 * z を計算し、前者が大きい場合 true となる。 このように比較の中に複雑な式を書くこともできます。

条件判定の and/or

教科書 pp.30-31 を参照してください。

複数の条件を組み合わせて、より複雑な条件式を書くことができます。 2 つの条件式を組み合わせて複雑な条件をつくるため、 「かつ」や「または」などの意味を持つ演算子があります。

演算子 意味
&& 「〜かつ〜」 論理演算としての and
|| 「〜または〜」 論理演算としての or
! 「〜ではない」 論理演算としての not

たとえば、x >= 1 && x <= 10 は、x が 1 以上 かつ x が 10 以下の場合、 つまり x が 1 〜 10 の範囲の中にあれば true になります。

また x == 0 || y > z + 1 は、 x が 0 に等しいか、または yz + 1 より大きい場合に true になります。

これらの例から && を「かつ」、 || を「または」と読めば良さそうです。

しかし、 日本語での表現はプログラムでの条件式の意味と異なる場合があります。 たとえば、「xa または b に等しい」 という言い方をそのまま訳して x == a || b と書くのは間違いです。 この場合は、日本語を 「xa に等しい、または xb に等しい」 と言わなければならないのです。 これを訳して x == a || x == b とするのが正解です。

また、x の値が 1 〜 10 の範囲内にあることを 1 <= x <= 10 と書くのは誤りで、正しくは x >= 1 && x <= 10 です。

例題: 3つの整数から最大値を求める

3 つの値 x, y, z の最大値を求めて出力するプログラム例を 3 とおり示します。 同じ仕事をするプログラムでありながら、 少しずつ違う書き方になっています。 if 文の使い方としてよく現れる書き方も含まれているので、 それらの点に注目しましょう。

1. 変数の比較だけを行う方式

最初に示すプログラムは、 3 つの変数の値を 2 つずつ比較して、 最大のものを見つけようという方針です。

class Max3a {
    public static void main(String[] args) {
	int x = 5;
	int y = 2;
	int z = 3;
	int max;

	if (x > y)
	    if (x > z)
		max = x;
	    else
		max = z;
	else
	    if (y > z)
		max = y;
	    else
		max = z;

	System.out.println("最大値は " + max + " です");

    }
}

最初に xy を比較する if 文があります。 x が大きければ、 else の前の文を実行します。 この場合の else の前の文とは、 if (x > z) max = x; else max = z; 全体です。 また、 else の後の文は、 if (y > z) max = x; else max = z; 全体です。
(if 文全体を一つの文として扱うということを思い出してください。)

xy より大きければ、 xz の大きい方が最大となります。 そうでなければ (yx 以上であれば) 、 yz の大きい方が最大となります。 内側の if 文で、 xz または、 yz の大きい方を変数 max に代入していま す。

この方法は実はあまり勧められるものではありません。 変数が 3 つだから良いようなものの、 変数の数が増えると条件分岐が複雑になってしまうからです。

2. and を使う方法

次のプログラムは、起こり得るすべての条件を and で結び記述したものです。

class Max3b {
    public static void main(String[] args) {
	int x = 5;
	int y = 2;
	int z = 3;
	int max;

	if (x >= y && x >= z)
	    max = x;
	else if (y >= x && y >= z)
	    max = y;
	else
	    max = z;

	System.out.println("最大値は " + max + " です");

    }
}

最初の if 文では、 xy よりも大きく、 なおかつ xz よりも大きいとき、 maxx の値を代入します。

else の後の if 文も同様に、 y が最大のときの動作を記述しています。 最後の else以降は、 x が最大でもなく y が最大でもない、 つまり z が最大の場合を記述しています。
この書き方も、やはり変数の数が増えると条件が複雑になる欠点があります。

ただし、教科書 p.44のように、 実際のプログラムでは、

if ( 条件1 )
        文1
else if ( 条件2 )
        文2
……
else if ( 条件k-1 )
        文k-1
else
        文k

という書き方はよく用いられます。覚えておきましょう。

これは、先頭から条件1、条件2、 …と順に計算していって、最初に真 (true) になった条件i に対応する文iだけ実行するという意味です。 条件k-1まで、すべて偽 (false) であれば、 最後の文kを実行します。

3. 変数に途中までの最大値を代入していく方法

class Max3c {
    public static void main(String[] args) {
	int x = 5;
	int y = 2;
	int z = 3;
	int max;

	max = x;
	if (y > max)
	    max = y;
	if (z > max)
	    max = z;

	System.out.println("最大値は " + max + " です");

    }
}

最大値を求めるプログラムとしては、これがお勧めです。 変数 x, y, z を一つずつ max と比較して、 もし大きければ、その値を max に代入していきます。

こうすることによって、その時点までに調べた変数の中での最大値が max に常時格納されていることになります。 この操作を最後の変数までくり返せば、全体の最大値が得られます。

このプログラムの書き方であれば、 変数の個数が少しくらい増えても見通しの良いプログラムになります。

演算子のあれこれ

Java では、式には一般的な四則演算の他に様々な計算式を書くことができます。

増分、減分演算子

次のような式を考えてみましょう。

a = a + 1;

この式の意味は、元の a に 1 を加え新たに aに代入する、ということです。 すなわち、元の a を 1 増やすという働きをする式です。

Java では、変数の値を 1 増やしたり、1 減らしたりする働きを持つ ++, -- という演算子が用意されています。 先ほどの例と、

a++;

は同じことになります。また ++a と書いても構いません。

-- 演算子は、指定された変数の値を 1 減らすことを行います。 a = a - 1 という式は a--; と同じことです。

++ や -- を用いると、変数名を 1 回しか書かなくて済むし、 1 だけ増やす (減らす) という意味を明確に表現することができます。

a++++a も、主な目的は変数の値を変化させることですが、 式である以上、これらも値を持っています。 a++++a の違いは、 a++ の値が変化させる前の古い a の値であるのに対し、 ++a は変化させたあとの新しい a の値であるということです。

たとえば、a の値が 5 であったとき、

b = a++;

とした場合、 b の値は 5 となり、

b = ++a;

とすれば b の値は 6 となります。

実際のソフトウェアでは、 変数の値を 1 ずつ増やしながら順番に仕事をしていく、 ということが良く行われます。 変数の値を 1 増やすことをインクリメント (increment) 、 1 減らすことをデクリメント (decrement) と言います。

複合代入

次のようなプログラムを考えてみます。

a = a + 10;

この式の意味は、元々の a の値を 10 増やすということです。 このような式も次のように書くことができます。

a += 10;

この書き方は + だけに限らず、 他の四則演算や余剰 (%) などに対して適用できます。