Java | 基礎文法:複合代入演算子

Java Java
スポンサーリンク

複合代入演算子の全体像

複合代入演算子は「計算して、その結果を同じ変数に代入する」操作を一行で書ける記法です。x += yx = x + yx *= yx = x * y と同義で、読みやすさと意図の明確さを両立できます。代入は右辺が先に評価され、その結果を左辺へ反映します。複合代入は「更新処理」を端的に表すため、ループや累積、フラグ操作で多用します。


算術系の複合代入(+=, -=, *=, /=, %=)

+= は加算して代入、-= は減算して代入、*= は乗算して代入、/= は除算して代入、%= は剰余を計算して代入します。整数に対する /= は小数切り捨てになり、%= は負の数のとき符号に注意が必要です。

int n = 10;
n += 3;  // 13
n -= 2;  // 11
n *= 4;  // 44
n /= 5;  // 8(整数の割り算は切り捨て)
n %= 3;  // 2(余り)
Java

小数を伴う更新では、意図した型へ変換してから複合代入すると安全です。例えば割引率を掛けるときは double を使い、丸めは表示側で行うと設計が安定します。

double price = 1999.5;
price *= 0.9;                      // 10% 引き
System.out.printf("%.2f%n", price);// 表示は小数2桁に丸め
Java

ビット・論理の複合代入(&=, |=, ^=, <<=, >>=, >>>=)

ビット演算の複合代入は、フラグ管理や低レベル操作に向いています。|= は付与、&= は除去(組み合わせに ~ を使う)、^= はトグル、<<= は左シフト、>>= は符号付き右シフト、>>>= はゼロ埋め右シフトです。

int READ = 0b0001, WRITE = 0b0010, EXEC = 0b0100;

int perm = 0;
perm |= READ;          // READ を付与
perm |= WRITE;         // WRITE を付与
perm &= ~READ;         // READ を除去(NOT と AND の組み合わせ)
perm ^= EXEC;          // EXEC をトグル(ON/OFF 切り替え)
Java

ブール型に対する &=|= は「論理 AND/OR(非短絡)」として動作します。^= は「論理 XOR」で、真偽を反転するトグルに応用できます。

boolean enabled = true;
enabled ^= true; // false(XOR:片方だけ真なら真 → 反転になる)
Java

シフトはビット列の位置を動かすため、マスクやエンコード/デコードに使います。

int x = 0b0001;
x <<= 3;   // 0b1000
x >>= 1;   // 0b0100(符号付き右シフト)
Java

型とキャストの仕様(重要ポイントの深掘り)

複合代入は「左辺の型へ暗黙キャスト」されるのが特徴です。通常の代入計算では中間結果が int になるため short/byte に戻せずコンパイルエラーになりますが、複合代入は暗黙キャストが入るため通ります。

short s = 1;
// s = s + 1;   // NG:s + 1 が int になり、short へ暗黙変換できない
s += 1;          // OK:複合代入が暗黙キャストを行う
Java

この仕様に頼りすぎると境界でのバグを招きます。安全策は「最初から int を使う」か、「明示キャストで意図を示す」ことです。さらに、整数のオーバーフローは例外にならず静かに壊れるため、増減が大きい可能性があるなら long を選ぶか、更新後に境界チェックを入れます。

int m = Integer.MAX_VALUE;
m += 1; // -2147483648(循環。要注意)
Java

評価順序と短絡でない論理(重要ポイントの深掘り)

&&|| は短絡評価ですが、&=|= は「必ず右辺を評価」します。副作用のあるメソッド呼び出しを条件に含めると、思わぬ動きになります。

static boolean logTrue() {
    System.out.println("右が評価された");
    return true;
}

public static void main(String[] args) {
    boolean ok = false;

    ok = ok && logTrue(); // 左が false → 右は評価されない(短絡)
    ok = false;           // リセット
    ok &= logTrue();      // 非短絡:右を必ず評価する(ログが出る)
}
Java

条件分岐には短絡の &&/|| を使い、&=/|= は「右を必ず評価したい理由があるとき」だけに限定すると安全です。


文字列と不変オブジェクトでの複合代入

String は不変(immutable)なので、+= は「新しい文字列を生成して再代入」します。短い連結なら可読性のために許容されますが、ループで多用すると大量のオブジェクトを作ってしまい非効率です。編集が多い場合は StringBuilder を使ってから最後に toString() へ変換するのが定石です。

String title = "Java";
title += " Basics";    // 新しい String へ置き換え

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
    sb.append("item").append(i).append('\n');
}
String result = sb.toString();
Java

BigDecimalBigInteger のような不変オブジェクトは、+= では更新できません。addmultiply の戻り値を再代入する形にします。

import java.math.BigDecimal;

BigDecimal price = new BigDecimal("1999.50");
price = price.multiply(new BigDecimal("0.9")); // 10% 引き
Java

例題で身につける

累積合計と平均

public class SumAvg {
    public static void main(String[] args) {
        int sum = 0;
        int[] nums = {3, 8, 2, 7};
        for (int n : nums) {
            sum += n; // 累積
        }
        double avg = sum / (double) nums.length;
        System.out.printf("sum=%d avg=%.2f%n", sum, avg);
    }
}
Java

ペナルティ更新と下限ゼロ

public class Penalty {
    public static void main(String[] args) {
        int points = 10;
        points -= 12;                 // -2
        points = Math.max(points, 0); // 下限ゼロへ正規化
        System.out.println(points);   // 0
    }
}
Java

権限フラグの付与・除去・トグル

public class Flags {
    public static void main(String[] args) {
        int READ = 1, WRITE = 2, EXEC = 4;
        int perm = 0;

        perm |= READ;   // 付与
        perm |= WRITE;  // 付与
        perm &= ~READ;  // 除去
        perm ^= EXEC;   // トグル

        System.out.println(perm);
    }
}
Java

シフトでビット位置を管理

public class Shift {
    public static void main(String[] args) {
        int mask = 1;
        mask <<= 5; // 32 の位置へ
        System.out.println(mask); // 32
    }
}
Java

設計の指針(重要ポイントのまとめ)

複合代入は「更新の意図」を短く明快に示す強力な表現です。short/byte に対する暗黙キャストの例外仕様に頼りすぎず、型は揃えて安全側で選ぶのが基本です。整数のオーバーフローは沈黙するため、範囲を見積もり long や正規化で守りましょう。論理の複合代入(&=/|=)は非短絡であることを理解し、条件分岐には短絡演算子を使って安全な評価順序を設計します。文字列の += は短い連結に限定し、繰り返し編集は StringBuilder へ。不変オブジェクトはメソッドの戻り値を再代入する形で扱う——この流儀を徹底すれば、更新処理のバグは大幅に減ります。

タイトルとURLをコピーしました