3.1 真偽の判定
3.1.1 関係演算子
プログラムは、定められた手順を単純実行するだけではなく、時にはデータを分析して、実行するべきコードを選択しなければなりません。つまり、プログラムを状況に応じて分岐させたり、繰り返したりするのです。そこで、プログラムの制御を行うには判断が必要です。例えば「変数 i が 10 以上であれば~する」とか「変数 i が変数 j と等しければ~しない」など、様々な状況判断が考えられるでしょう。
このように、特定の値を調べるには関係演算子を用います。関係演算子はその結果に応じて true か false (すなわち boolean 型) を返します。
関係演算では「A が B と等しいか」ということを調べ、A が B と等しければ true を返すのです。このような状態を真であると表現します。逆に、A が B と等しくなければ false を返します。このような状態を偽であると表現します。
演算子 | 効果 | 例 |
---|---|---|
< | 左オペランドが右オペランドより小さければ true | A < B |
<= | 左オペランドが右オペランド以下であれば true | A <= B |
> | 左オペランドが右オペランドより大きければ true | A > B |
>= | 左オペランドが右オペランド以上であれば true | A >= B |
== | 双方のオペランドが等しければ true | A == B |
!= | 双方のオペランドが等しくなければ true | A != B |
! | オペランドが true ならば false、false ならば true | !A |
instanceof | 左オペランドが右オペランドの型にキャスト可能な場合は true | A instanceof Object |
<、<=、>、>= 演算子は数値の比較を行うための関係演算子です。双方のオペランドには数値型以外を指定することはできません。一般に、これらを数値比較演算子と呼びます。
== や != は数値や boolean 型など、すべての型を指定することができます。双方のオペランドが保有する値が同じかどうかを調べるためのもので、等値演算子と呼ばれます。
! は論理否定演算子と呼ばれる単項演算子で、オペランドは常に boolean 型でなければなりません。この演算子は、与えられた boolean を単純に反転させます。
instanceof 演算子は特別なもので、これはクラスと継承について十分に学習し、オブジェクト指向の本質を理解してはじめて意味がわかるものでしょう。この関係演算子については後述することにします。
class Test { public static void main(String args[]) { String str = "10 == 100 = " + (10 == 100) + '\n' + "'A' == 0x41 = " + ('A' == 0x41) + '\n' + "-0 == +0 = " + (-0 == +0) + '\n' + "1000 < 500 = " + (1000 < 500) + '\n' + "1000 > 500 = " + (1000 > 500); System.out.println(str); } }
>java Test 10 == 100 = false 'A' == 0x41 = true -0 == +0 = true 1000 < 500 = false 1000 > 500 = true
コード1から興味深い結果が得られています。
最初の 10 == 100 という関係演算は理解できるでしょう。10 は 100 と等しくないため false が返されます。次の 'A' == 0x41 の結果は true、すなわち等しいとされていますが、Unicode 文字 A は数値 0x41 と等しいので、うなずける結果です。
-0 == +0 の結果は true すなわち等しいとされています。Java では、正のゼロと負のゼロは等しいと定義されているのです。
3.1.2 条件 And、Or 演算子
関係演算子は値の比較の結果から、true か false を返すというものでした。より複雑な関係を調べる場合、複数の条件が満たされているかどうかを調べなければならないことがあります。「~かつ~である」とか「~または~である」という判定を行いたいとすれば、二つの boolean 型から論理演算によって結果を導かなければなりません。
論理演算子の論理積演算子 &、論理和演算子 |、排他的論理和演算子 ^ は boolean 型のオペランドを受け取ることもできるため、これらを使えば複数の条件が満たされているかどうかを判定することができます。
しかし、これ以外に、boolean 型専用の条件論理積演算子 &&、及び、条件論理和演算子 || が用意されています。これらの演算子の働きは、論理積演算子、及び論理和演算子と等しいものですが、結果が確定した時点で評価を中断するという部分が異なります。
論理積では左オペランドを評価した結果が false であれば、右オペランドの値が何であれ、結果は false になることが確定します。ならば、右オペランドの評価を省略して速度を向上させるべきだと思うことでしょう。これを実現するのが条件論理積、論理和演算子なのです。論理和も同様で、左オペランドの結果が true であれば、右オペランドの値何であれ、結果は true になることが確定します。
class Test { public static void main(String args[]) { int iValue = 0; String str = //条件論理積演算子の評価 "false && (++iValue == 0) = " + (false && (++iValue == 0)) + '\n' + "iValue = " + iValue + '\n' + "true && (++iValue == 0) = " + (true && (++iValue == 0)) + '\n' + "iValue = " + iValue + '\n' + //通常の論理積演算子の評価 "false & (++iValue == 0) = " + (false & (++iValue == 0)) + '\n' + "iValue = " + iValue; System.out.println(str); } }
>java Test false && (++iValue == 0) = false iValue = 0 true && (++iValue == 0) = false iValue = 1 false & (++iValue == 0) = false iValue = 2
コード2は、条件論理積演算子の効果を証明するものです。
最初の式 false && (++iValue == 0) では、左オペランドが false であることから、この論理積の結果が常に false であることが確定されています。そのため、条件論理積演算子では右オペランドの評価を省略して false を返します。その証拠に、右オペランドが評価された場合は ++iValue が実行され、iValue の値がインクリメントされているはずですが、直後の iValue の値は 0 になっています。これは、前置インクリメント演算子が評価されていないことを証明しています。もちろん、左オペランドが true の場合は結果を確定することができないため、右オペランドが評価されます。
通常の論理積演算子は、条件論理積演算子と同じ結果を得ることができますが、右オペランドも確実に評価される点で異なっています。実行結果を見れば、左オペランドが false であり、この時点で結果が確定しているにもかかわらず、右オペランドを評価していることが iValue の値から確認できます。