この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: 演算子
SEOタイトル: Java 演算子完全リファレンス

この記事の要点
  • 算術演算子: + - * / %。整数同士の / は切り捨て、% は剰余
  • 比較 / 論理: == != < > <= >= / && || !オブジェクトは == でなく equals() で内容比較
  • ビット演算: & | ^ ~ << >> >>>>>> は符号なし右シフト
  • 三項演算子 ?: + instanceof。Java 14+ で instanceof Pattern Matching
  • 優先順位は覚えるより括弧で明示。バグの 9 割は優先順位の勘違い

算術演算子

int a = 10, 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  ★ 剰余

// 浮動小数で計算したい場合は片方を double に
System.out.println((double) a / b);    // 3.3333...
System.out.println(a / (double) b);    // 3.3333...

// 文字列連結も + で
String s = "x = " + a;        // "x = 10"

// オーバーフロー(int は約 21 億まで)
int max = Integer.MAX_VALUE;  // 2_147_483_647
System.out.println(max + 1);  // -2147483648 ★ ラップアラウンド

// 安全な演算 (Java 8+)
int safe = Math.addExact(max, 1);    // ArithmeticException

代入演算子

演算子等価な式
=x = 5-
+=x += 3x = x + 3
-=x -= 3x = x - 3
*=x *= 3x = x * 3
/=x /= 3x = x / 3
%=x %= 3x = x % 3
&=x &= 3x = x & 3
|=x |= 3x = x | 3
^=x ^= 3x = x ^ 3
<<=x <<= 3x = x << 3
>>=x >>= 3x = x >> 3

比較演算子と参照比較の罠

// プリミティブの比較: 値の比較
int a = 1, b = 1;
System.out.println(a == b);    // true

// オブジェクトの比較: ★ 参照比較になる!
String s1 = new String("hello");
String s2 = new String("hello");

System.out.println(s1 == s2);          // false ★ 別インスタンス
System.out.println(s1.equals(s2));     // true  ★ 内容比較

// String リテラルは「文字列プール」で同一インスタンス化される
String s3 = "hello";
String s4 = "hello";
System.out.println(s3 == s4);          // true ★(同じプールを参照)

// Integer の罠
Integer i1 = 127, i2 = 127;
Integer i3 = 128, i4 = 128;
System.out.println(i1 == i2);     // true  ★ -128〜127 はキャッシュ
System.out.println(i3 == i4);     // false ★ 128 以上は別インスタンス
System.out.println(i3.equals(i4));// true

// ★ ルール: オブジェクト同等性は必ず equals()

論理演算子

boolean a = true, b = false;

// 短絡評価 (Short-Circuit)
System.out.println(a && b);    // false。a が false なら b 評価しない
System.out.println(a || b);    // true。 a が true なら b 評価しない
System.out.println(!a);        // false

// 非短絡(左右両方評価)
System.out.println(a & b);     // false
System.out.println(a | b);     // true

// null セーフ
String s = null;
if (s != null && s.length() > 0) {    // ★ && が短絡なので NPE 起きない
    // ...
}

// ❌ 順序を逆にすると NPE
if (s.length() > 0 && s != null) {    // NullPointerException
    // ...
}

ビット演算子

int a = 0b1100;    // 12
int b = 0b1010;    // 10

System.out.println(Integer.toBinaryString(a & b));    //  1000 (AND)
System.out.println(Integer.toBinaryString(a | b));    //  1110 (OR)
System.out.println(Integer.toBinaryString(a ^ b));    //  0110 (XOR)
System.out.println(Integer.toBinaryString(~a));       //  ...11110011 (NOT, 補数)

// シフト演算
int n = 8;                         // 1000
System.out.println(n << 2);        // 32   (100000)  ← 左シフト = ×2^2
System.out.println(n >> 1);        // 4    (100)    ← 右シフト = ÷2

// >>> 符号なし右シフト(Java 独自)
int neg = -1;                      // 0xFFFFFFFF
System.out.println(neg >> 1);      // -1(符号維持)
System.out.println(neg >>> 1);     // 2147483647(先頭に 0 を詰める)

// 用途: ビットフラグ
int FLAG_READ = 1;       // 001
int FLAG_WRITE = 2;      // 010
int FLAG_EXEC = 4;       // 100

int perms = FLAG_READ | FLAG_WRITE;    // 011
if ((perms & FLAG_WRITE) != 0) {
    System.out.println("write permission");
}

インクリメント / デクリメント

int a = 5;

// 前置: 先にインクリメント
int b = ++a;    // a=6, b=6

// 後置: 評価後にインクリメント
int c = a++;    // c=6, a=7

// ループでよく使う
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

// ★ 同じ式で複数回使うのは未定義動作の元
int x = 5;
int y = x++ + ++x;    // 言語仕様上は確定するが可読性が悪い → 避ける

三項演算子

int age = 20;
String category = (age >= 18) ? "adult" : "minor";

// ネストはなるべく避ける(可読性低下)
String grade = score >= 80 ? "A"
             : score >= 60 ? "B"
             : score >= 40 ? "C"
             : "F";

// null チェック
String name = (user != null) ? user.getName() : "anonymous";

// Java 9+ Optional のほうが読みやすい場合も
String name2 = Optional.ofNullable(user)
                       .map(User::getName)
                       .orElse("anonymous");

instanceof と Pattern Matching

Object obj = "hello";

// 旧来の instanceof
if (obj instanceof String) {
    String s = (String) obj;        // ★ キャストが必要
    System.out.println(s.length());
}

// Java 16+ Pattern Matching for instanceof
if (obj instanceof String s) {       // ★ キャスト不要、変数 s で使える
    System.out.println(s.length());
}

// Java 21 Pattern Matching for switch
String describe(Object o) {
    return switch (o) {
        case Integer i -> "int: " + i;
        case String s  -> "str: " + s;
        case null      -> "null";
        default        -> "other";
    };
}

演算子の優先順位 (一部)

順位演算子
1 (高)後置 ++ -- , . , () , []a++
2前置 ++ -- + - ! ~ , キャスト++a , (int) x
3* / %a * b
4+ -a + b
5<< >> >>>a << 2
6< > <= >= instanceofa < b
7== !=a == b
8&a & b
9^a ^ b
10|a | b
11&&a && b
12||a || b
13?: 三項a ? b : c
14 (低)= += -= ... 代入a = b

原則: 優先順位を覚えるより括弧で明示if ((a & FLAG) != 0) のように。

FAQ

Q: String の比較は == でも動く時があるが?
A: コンパイル時定数(リテラル)は文字列プールに格納され同一参照になります。ただし依存すべきではなく、必ず equals() を使ってください。

Q: i == i + 1 は常に false?
A: int の場合は常に false。ただし double では巨大な値で 1.0e20 == 1.0e20 + 1 が true になります(精度不足)。

Q: NaN == NaN は?
A: false。NaN は自分自身とも等しくありません。判定は Double.isNaN(x) を使う。