04_演算子

対象:C言語経験者 / C言語との差分と試験頻出ポイントを中心に理解します


■ 1. C言語との差分

演算子の種類はC言語とほぼ同じです。まず違いだけ確認しましょう。

演算子JavaC言語
算術 + - * / %同じ同じ
インクリメント ++ --同じ(前置・後置あり)同じ
関係 == != < > <= >=同じ同じ
論理 && || !同じ同じ
ビット & | ^ ~ << >>ほぼ同じほぼ同じ
符号なし右シフト >>> Java追加あり(符号ビットを0で埋める)なし
代入 = += -= *= /= %=同じ同じ
条件(三項) ? :同じ同じ
文字列連結 +String に使えるなし(strcatを使う)
instanceof Java追加型の確認に使う(後の単元で学ぶ)なし
ほとんどC言語と同じです。この単元では 試験によく出る3つ に絞って深く学びます。
① インクリメント/デクリメントの前置・後置 ② 演算子の優先順位 ③ 代入演算子の結合則

■ 2. インクリメント・デクリメント(試験最頻出)

++-- はC言語と同じですが、前置と後置の違いが試験で繰り返し出題されます。

● 前置と後置の違い

前置(++a) 先に加算してから、その値を使う int a = 5; int b = ++a; a = 6 b = 6 ① a を 5→6 に加算 ② 加算後の値 6 を b に代入 後置(a++) 今の値を使ってから、その後で加算 int a = 5; int b = a++; a = 6 b = 5 ① 今の値 5 を b に代入 ② その後 a を 5→6 に加算
前置は「先に変えてから使う」。後置は「使ってから変える」。
単独で使う場合(a++;++a;)は結果が同じです。
違いが出るのは b = a++println(++a) のように、別の式の中で使うときだけです。

● whileループでの前置デクリメント(試験第67回 問4(24))

int a = 5;
while (a > 0) {
    System.out.println(--a);  // 前置デクリメント
    a--;
}
この出力を考えてみましょう(答えを見る前に自分で予想してください)

出力:

4 2 0

流れ:

ループ開始時の awhile 条件--a の値(表示)a-- 後の a
55 > 0 → 続行--a → a=4、表示:4a-- → a=3
33 > 0 → 続行--a → a=2、表示:2a-- → a=1
11 > 0 → 続行--a → a=0、表示:0a-- → a=-1
-1-1 > 0 → 終了

■ 3. 演算子の優先順位

C言語と同じルールです。よく出るポイントに絞って確認します。

高い(先に計算) ++ -- ! ~ 単項- * / % + - < > <= >= instanceof == != 低い(後で計算) && || ?: = += -= …
上ほど優先順位が高く、先に計算されます。C言語とほぼ同じです。

● 試験で問われやすいパターン

// ① 単項マイナスと二項マイナスの混在(第67回 問3(17))
int a = 6;
System.out.println(-a - 2);  // → -8
// 単項の「-a」が先に評価されて -6 になる。その後「-6 - 2」= -8

// ② 乗算が加算より先(第63回 問3(19))
int w = 3;
System.out.println(3 + w * 6);  // → 21
// w * 6 = 18 が先。その後 3 + 18 = 21

// ③ 文字列連結と加算の混在(02_クラスとmain で既出)
System.out.println("結果: " + 3 + 2);    // → 結果: 32
System.out.println("結果: " + (3 + 2));  // → 結果: 5
単項演算子(-a!flag)は 二項演算子(a - b)より優先順位が高いです。
迷ったときはカッコで明示するのが最も確実な方法です。

■ 4. 代入演算子の結合則(右から左)

代入演算子が複数並んだとき、右から左に評価されます。

// 第63回 問3(20)
int p = 7, q = 5;
q += p -= 4;
System.out.println(p + " " + q);
出力を考えてみましょう(答えを見る前に予想してください)
3 8

右から左に評価するため、p -= 4 が先に実行されます。

q += p -= 4 ステップ①(右から) p -= 4 → p = 7-4 = 3 ステップ②(左へ) q += 3 → q = 5+3 = 8 p = 3, q = 8

p -= 4 が評価されて p = 3 になります。その結果の 3q += の右辺として使われるので q = 5 + 3 = 8 になります。


■ 5. 論理演算子の短絡評価

C言語と同じ動作ですが、Javaでも重要な知識です。

演算子短絡評価の動作
&& 左辺が false なら右辺を評価しない a != 0 && 10/a > 1
(a=0のとき右辺でゼロ除算が起きない)
|| 左辺が true なら右辺を評価しない flag || expensiveMethod()
(flagがtrueなら重い処理をスキップ)
試験では「&&& の違い」が問われることがあります。
&& は短絡評価あり、& は短絡評価なし(必ず両辺を評価)。通常は && を使います。

■ 6. 条件演算子(三項演算子)

C言語と全く同じです。条件式 ? 真の値 : 偽の値 という構文です。

int a = 10, b = 3;
String result = (a > b) ? "aの方が大きい" : "bの方が大きい";
System.out.println(result);  // → aの方が大きい

// if 文で書いた場合と等価
String result2;
if (a > b) {
    result2 = "aの方が大きい";
} else {
    result2 = "bの方が大きい";
}
第63回 問4(26) で条件演算子が出題されています(c == 'a' ? "真" : "偽")。

■ 実習1:インクリメント/デクリメントの確認

実習1

04_IncrDecr フォルダに IncrDecr.java を作って実行しましょう。

public class IncrDecr {
    public static void main(String[] args) {

        // 前置と後置の違い
        int a = 5;
        int b = ++a;  // 前置:先に加算してから b に代入
        System.out.println("前置 ++a:  a=" + a + ", b=" + b);

        int c = 5;
        int d = c++;  // 後置:先に d に代入してから加算
        System.out.println("後置 c++:  c=" + c + ", d=" + d);

        System.out.println();

        // println の中での前置・後置
        int x = 3;
        System.out.println("--x = " + (--x));  // 前置:表示前に減算
        System.out.println("x   = " + x);

        int y = 3;
        System.out.println("y-- = " + (y--));  // 後置:表示後に減算
        System.out.println("y   = " + y);
    }
}

実行結果:

前置 ++a: a=6, b=6 後置 c++: c=6, d=5 --x = 2 x = 2 y-- = 3 y = 2

● 動いたら変えてみましょう

#変えてみること確認ポイント
1 int b = ++a;int b = a++; に変える a と b の値がどちらも変わることを確認しましょう
2 System.out.println("--x = " + (--x)); のカッコを外して "--x = " + --x にする 結果は同じですが、演算子の優先順位に慣れるための確認です
3 次のコードを追加して出力を予想してから実行しましょう:
int n = 10; System.out.println(n-- + " " + n);
後置デクリメントがいつ評価されるか確認しましょう

■ 実習2:優先順位と代入演算子の確認

実習2

05_Operators フォルダに Operators.java を作って実行しましょう。

public class Operators {
    public static void main(String[] args) {

        // ① 単項マイナスと二項マイナス
        int a = 6;
        System.out.println(-a - 2);       // → -8(単項 -a が先)
        System.out.println(-(a - 2));     // → -4(カッコで変わる)

        // ② 乗算の優先順位
        int w = 3;
        System.out.println(3 + w * 6);    // → 21(w*6 が先)
        System.out.println((3 + w) * 6);  // → 36(カッコで変わる)

        // ③ 代入演算子の右結合
        int p = 7, q = 5;
        q += p -= 4;                      // 右から:p=3、次にq=8
        System.out.println("p=" + p + ", q=" + q);

        // ④ 条件演算子
        int score = 75;
        String grade = (score >= 60) ? "合格" : "不合格";
        System.out.println(grade);

        // ⑤ 論理演算子の短絡評価
        int x = 0;
        boolean result = (x != 0) && (10 / x > 1);  // x=0でもゼロ除算しない
        System.out.println("短絡評価: " + result);
    }
}

実行結果:

-8 -4 21 36 p=3, q=8 合格 短絡評価: false

● 動いたら変えてみましょう

#変えてみること確認ポイント
1 (x != 0) && (10 / x > 1)&&& に変える 短絡評価がなくなるため x=0 でゼロ除算が起きて実行時エラーになることを確認しましょう
2 int p = 7, q = 5; の値を変えて q += p -= 4 を再度確認する 右から左への評価順序を自分の手で追えるようになりましょう
3 score = 59 に変える 条件演算子の分岐を確認しましょう

■ 試験(問3・問4)との対応

頻出ポイント

よく問われること正しい答え
前置 ++a先に加算してから式の値として使う
後置 a++今の値を式の値として使ってから加算
単項マイナス -a - 2(a=6)単項 -a が先 → -6-2 = -8
3 + w * 6(w=3)* が先 → 3+18 = 21
q += p -= 4(p=7,q=5)右から:p=3、q=8
&&& の違い&& は短絡評価あり、& はなし
練習問題:次の出力を答えましょう(第67回 問4(24) 類似)
public class Q {
    public static void main(String[] args) {
        int a = 5;
        while (a > 0) {
            System.out.println(--a);
            a--;
        }
    }
}
4 2 0

トレースのポイント:--a は前置なので println に渡す前に a を減らします。その後さらに a-- で1減らします。1ループで a が2減ります。

練習問題2:次の出力を答えましょう(第63回 問3(20) 類似)
public class Q2 {
    public static void main(String[] args) {
        int p = 7, q = 5;
        q += p -= 4;
        System.out.print(p);
        System.out.print(", ");
        System.out.print(q);
    }
}
3, 8

右から左:① p -= 4 → p=3 ② q += 3 → q=8


■ まとめ

ポイント内容
前置 ++a先に変えてから使う
後置 a++使ってから変える
優先順位単項 > * / % > + - > 関係 > == != > && > || > 代入
代入演算子の結合則右から左に評価される
短絡評価&& は左が false なら右を評価しない
>>>符号なし右シフト(Javaだけにある)
条件演算子条件 ? 真の値 : 偽の値(C言語と同じ)