Java 演算子
演算子(Operators)は、あらゆるプログラミング言語の屋台骨(スケルトン)であり、計算の実行、データの比較、およびプログラムフローの制御を可能にします。Javaにおいて、演算子は1つ、2つ、または3つのオペランド(変数または値)に対して特定の操作を実行するための特殊な記号です。演算子をしっかりとマスターすることは、効率的なJavaコードを記述するための重要な前提条件です。
本章では、算術演算子、関係演算子、および論理演算子について包括的に解説し、プログラム内でのデータ処理や意思決定に不可欠なツールを提供します。
1. 算術演算子
算術演算子は数学的な計算を行うために使用されます。Javaは、2つのオペランドを必要とする「二項算術演算子」と、1つのオペランドのみで動作する「単項演算子」を提供しています。
1.1 二項算術演算子
これらの演算子は2つのオペランドを使用して計算を行います。
| 演算子 | 名称 | 説明 | 例 | 結果 |
|---|---|---|---|---|
+ | 加算 (Addition) | 2つのオペランドを足す。 | 5 + 3 | 8 |
- | 減算 (Subtraction) | 最初のオペランドから2番目のオペランドを引く。 | 5 - 3 | 2 |
* | 乗算 (Multiplication) | 2つのオペランドを掛ける。 | 5 * 3 | 15 |
/ | 除算 (Division) | 最初のオペランドを2番目のオペランドで割る。 | 15 / 3 | 5 |
% | 剰余 (Modulus) | 除算を行った後の余りを返す。 | 16 % 3 | 1 |
コード例:
public class ArithmeticExample {
public static void main(String[] args) {
int a = 10;
int b = 3;
System.out.println("加算: " + (a + b)); // 出力: 13
System.out.println("減算: " + (a - b)); // 出力: 7
System.out.println("乗算: " + (a * b)); // 出力: 30
System.out.println("除算: " + (a / b)); // 出力: 3 (注意:ここでは整数除算が行われる)
System.out.println("剰余 (余り): " + (a % b)); // 出力: 1
}
}解析: 上記のコードは、整数のオペランドを用いた二項算術演算を示しています。特に注意すべき点として、両方のオペランドが整数(int)の場合、除算演算子 / は整数除算を実行し、小数部分は切り捨てられます。
1.2 単項算術演算子
これらの演算子は、単一のオペランドに対してのみ操作を実行します。
| 演算子 | 名称 | 説明 | 例 | 結果 |
|---|---|---|---|---|
+ | 単項プラス (Unary plus) | short, byte, charをintに昇格させる。int以上の型には影響しない。 | +5 | 5 |
- | 単項マイナス (Unary minus) | 式の符号を反転させる。 | -5 | -5 |
++ | インクリメント (Increment) | オペランドの値を1増やす。前置 (++a) または後置 (a++) として使用可能。 | a++ または ++a | aがa+1になる |
-- | デクリメント (Decrement) | オペランドの値を1減らす。前置 (--a) または後置 (a--) として使用可能。 | a-- または --a | aがa-1になる |
コード例:
public class UnaryExample {
public static void main(String[] args) {
int a = 5;
System.out.println("a の初期値: " + a); // 出力: 5
System.out.println("単項プラス: " + (+a)); // 出力: 5 (変化なし)
System.out.println("単項マイナス: " + (-a)); // 出力: -5
System.out.println("後置インクリメント (Post-increment): " + (a++)); // 出力: 5 (現在のaの値を使用した後、aを1増やす)
System.out.println("後置インクリメント後の a の値: " + a); // 出力: 6
System.out.println("前置デクリメント (Pre-decrement): " + (--a)); // 出力: 5 (aを1減らした後、その新しい値を使用する)
}
}解析: インクリメント (++) とデクリメント (--) 演算子の挙動は、それらが前置か後置かによって異なります。
- 前置 (Prefix)(例:
++a): 変数aの値がまず増加し、その後に式の計算に使用されます。 - 後置 (Postfix)(例:
a++): 変数aの現在の値が式の計算に使用された後、自身の値が増加します。
1.3 複合代入演算子
Javaは、算術演算と代入操作を一つにまとめた「複合代入演算子」も提供しており、コードをより簡潔に記述できます。
| 演算子 | 例 | 等価な式 |
|---|---|---|
+= | a += b | a = a + b |
-= | a -= b | a = a - b |
*= | a *= b | a = a * b |
/= | a /= b | a = a / b |
%= | a %= b | a = a % b |
コード例:
public class CompoundAssignmentExample {
public static void main(String[] args) {
int a = 10;
a += 5; // a = a + 5 と同じ
System.out.println("a += 5: " + a); // 出力: 15
a -= 3; // a = a - 3 と同じ
System.out.println("a -= 3: " + a); // 出力: 12
a *= 2; // a = a * 2 と同じ
System.out.println("a *= 2: " + a); // 出力: 24
a /= 4; // a = a / 4 と同じ
System.out.println("a /= 4: " + a); // 出力: 6
a %= 2; // a = a % 2 と同じ
System.out.println("a %= 2: " + a); // 出力: 0
}
}2. 関係演算子
関係演算子は2つのオペランドを比較するために使用されます。関係演算の結果は常に boolean 値(true または false)となります。
| 演算子 | 名称 | 説明 | 例 (a=5, b=10) | 結果 |
|---|---|---|---|---|
== | 等しい | 両方のオペランドが等しければ true、そうでなければ false。 | a == b | false |
!= | 等しくない | 両方のオペランドが等しくなければ true、そうでなければ false。 | a != b | true |
> | より大きい | 最初のオペランドが2番目より大きければ true。 | a > b | false |
< | より小さい | 最初のオペランドが2番目より小さければ true。 | a < b | true |
>= | 以上 | 最初のオペランドが2番目以上であれば true。 | a >= b | false |
<= | 以下 | 最初のオペランドが2番目以下であれば true。 | a <= b | true |
コード例:
public class RelationalExample {
public static void main(String[] args) {
int a = 5;
int b = 10;
System.out.println("a == b: " + (a == b)); // 出力: false
System.out.println("a != b: " + (a != b)); // 出力: true
System.out.println("a > b: " + (a > b)); // 出力: false
System.out.println("a < b: " + (a < b)); // 出力: true
System.out.println("a >= b: " + (a >= b)); // 出力: false
System.out.println("a <= b: " + (a <= b)); // 出力: true
boolean isEqual = (a == 5);
System.out.println("isEqual (aは5と等しいか): " + isEqual); // 出力: true
}
}解析: 関係演算子は、条件分岐ステートメント(次モジュールで解説)において、特定の条件に基づいてプログラムの実行フローを制御するために極めて頻繁に使用されます。a == 5 のような比較が示すように、変数同士だけでなく、変数と具体的なリテラル(固定値)を比較することも可能です。
3. 論理演算子
論理演算子は、2つ以上のブール式を組み合わせるために使用されます。論理演算の結果も常に boolean 値(true または false)となります。
| 演算子 | 名称 | 説明 | 例 (a=true, b=false) | 結果 |
|---|---|---|---|---|
&& | 論理積 (AND) | 両方のオペランドが true の場合のみ true を返す。ショートサーキット特性を持つ。 | a && b | false |
|| | 論理和 (OR) | 少なくとも一方のオペランドが true であれば true を返す。ショートサーキット特性を持つ。 | a || b | true |
! | 論理否定 (NOT) | オペランドの論理値を反転させる。真は偽に、偽は真になる。 | !a | false |
& | ビット単位AND / 論理AND | &&に似ているが、ショートサーキットせず常に両辺を評価する。 | a & b | false |
| | ビット単位OR / 論理OR | ||に似ているが、ショートサーキットせず常に両辺を評価する。 | a | b | true |
^ | 排他的論理和 (XOR) | 一方が真で、もう一方が偽の場合のみ true を返す。 | a ^ b | true |
コード例:
public class LogicalExample {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
System.out.println("a && b: " + (a && b)); // 出力: false
System.out.println("a || b: " + (a || b)); // 出力: true
System.out.println("!a: " + (!a)); // 出力: false
System.out.println("a & b: " + (a & b)); // 出力: false
System.out.println("a | b: " + (a | b)); // 出力: true
System.out.println("a ^ b: " + (a ^ b)); // 出力: true
}
}詳細解説:
- ショートサーキット評価 (Short-circuiting):
&&と||演算子はショートサーキット挙動を持ちます。これは、左辺のオペランドを評価しただけで式全体の結果が確定する場合、Javaは右辺のオペランドを評価(実行)しないことを意味します。 - 例えば
a && bにおいて、aが既にfalseであれば、式全体の結果はfalseに確定するため、bは評価されません。 - 同様に
a || bにおいて、aが既にtrueであれば、結果はtrueに確定するため、bはスキップされます。 - ビット単位 vs 論理:
&と|は元来ビット演算子ですが、ブール値に対しても使用可能です。&&や||との最大の違いはショートサーキット特性がないことであり、左辺の結果に関わらず右辺の式が必ず実行されます。日常的な論理判断では、通常&&と||の使用が強く推奨されます。 - 排他的論理和 (XOR):
^は、両辺の状態が「異なる」(一方が真で他方が偽)場合にのみtrueを返します。両方とも真、あるいは両方とも偽の場合はfalseを返します。
3.1 演算子の組み合わせ
複数の演算子を組み合わせて、より複雑な式を作成できます。括弧 () を使用して演算の優先順位を制御できます。
コード例:
public class CombinedOperators {
public static void main(String[] args) {
int age = 25;
boolean isStudent = true;
// 割引対象かどうかをチェック(18歳未満 または 学生である)
boolean eligibleForDiscount = (age < 18) || isStudent;
System.out.println("割引資格の有無: " + eligibleForDiscount); // 出力: true
// 成人 かつ 学生ではない かどうかをチェック
boolean isAdultAndNotStudent = (age >= 18) && !isStudent;
System.out.println("成人かつ非学生: " + isAdultAndNotStudent); // 出力: false
}
}4. 演算子の優先順位
演算子の優先順位は、複雑な式の中で各演算子が実行される順番を決定します。優先順位の高い演算子は、低い演算子よりも先に評価されます。
以下は、解説した演算子の優先順位(高い順)です:
| 優先順位 | 演算子 |
|---|---|
| 1 | ++, -- (後置 Postfix) |
| 2 | ++, -- (前置 Prefix), + (単項正), - (単項負), ! |
| 3 | *, /, % |
| 4 | +, - |
| 5 | ==, !=, >, <, >=, <= |
| 6 | & |
| 7 | ^ |
| 8 | | |
| 9 | && |
| 10 | || |
| 11 | =, +=, -=, *=, /=, %= (代入系) |
コード例:
public class OperatorPrecedence {
public static void main(String[] args) {
int a = 5;
int b = 10;
int c = 2;
int result = a + b * c; // 乗算は加算より優先順位が高い
System.out.println("a + b * c: " + result); // 出力: 25 (5 + (10 * 2) と同じ)
int result2 = (a + b) * c; // 括弧 () は最高優先順位。演算順序を強制的に変える
System.out.println("(a + b) * c: " + result2); // 出力: 30 ((5 + 10) * 2 と同じ)
boolean boolResult = a > b || b < c && a == 5;
System.out.println("括弧なしの論理組み合わせ: " + boolResult); // 出力: false
/* 実行順序の解析:
1. まず && の両辺を評価: b < c は false (10 < 2)
2. 関係演算 a == 5 は true (5 == 5)
3. false && true の結果は false
4. 次に || の両辺を評価: a > b は false (5 > 10)
5. 最終結果: false || false は false
*/
}
}解析: 演算子の優先順位を覚えておくことは非常に重要です。これにより、プログラムが予期せぬ結果を出すのを防ぐことができます。順序が不明確な場合は、積極的に括弧 () を使用しましょう。これは実行順序を確実に保証するだけでなく、コードの可読性(人間にとっての読みやすさ)を大幅に向上させます。