Java 逆引き集 | Enum の使い方(プロパティとメソッド) — 定数管理

Java Java
スポンサーリンク

Enum の使い方(プロパティとメソッド) — 定数管理

「限られた選択肢」を型として安全に扱うのが enum。単なる定数集ではなく、プロパティやメソッドを持てる“小さなクラス”です。業務コードの「状態」「コード値」「表示名」を一箇所にまとめ、分岐をスッキリさせます。


基本構文と最小例

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
Java
  • 意味: Day は「この7つの値しか取り得ない」型になる。
  • 参照: Day today = Day.MONDAY;
  • 比較: == で安全に比較できる(同一インスタンス保証)。

プロパティ(フィールド)を持たせる

public enum OrderStatus {
    NEW("新規", 1),
    PAID("支払済み", 2),
    SHIPPED("出荷済み", 3),
    CANCELED("キャンセル", 9);

    private final String label; // 表示名
    private final int code;     // 外部連携用コード

    OrderStatus(String label, int code) {
        this.label = label;
        this.code = code;
    }
    public String getLabel() { return label; }
    public int getCode() { return code; }
}
Java
  • ポイント: enumのコンストラクタは常に private。各定数に引数を渡して初期化する。
  • 用途: 表示名、コード値、重み、色、ロール権限などをひとまとめに。

メソッドを持たせる(ロジック・変換)

public enum Severity {
    INFO(0), WARN(1), ERROR(2);

    private final int level;
    Severity(int level) { this.level = level; }
    public int level() { return level; }

    public boolean isSerious() { return level >= 1; }

    public static Severity fromLevel(int level) {
        for (Severity s : values()) {
            if (s.level == level) return s;
        }
        throw new IllegalArgumentException("未知レベル: " + level);
    }
}
Java
  • ポイント: values() は全定数を返す。逆引きに便利。
  • 変換メソッド: fromXxx を定義して、外部値→enum を集中管理。

switch と enum(分岐の定番)

public String actionMessage(OrderStatus s) {
    return switch (s) {
        case NEW      -> "注文を受付ました";
        case PAID     -> "入金確認済み";
        case SHIPPED  -> "配送中です";
        case CANCELED -> "キャンセルされました";
    };
}
Java
  • ポイント: switch は全ケース網羅をチェックするので抜け漏れ防止になる。

例題で身につける

例題1: 月の表示と日数(うるう年対応)

public enum Month {
    JAN(1, "1月"), FEB(2, "2月"), MAR(3, "3月"), APR(4, "4月"),
    MAY(5, "5月"), JUN(6, "6月"), JUL(7, "7月"), AUG(8, "8月"),
    SEP(9, "9月"), OCT(10, "10月"), NOV(11, "11月"), DEC(12, "12月");

    private final int number;
    private final String label;
    Month(int number, String label) { this.number = number; this.label = label; }
    public int number() { return number; }
    public String label() { return label; }

    public int days(boolean leapYear) {
        return switch (this) {
            case JAN, MAR, MAY, JUL, AUG, OCT, DEC -> 31;
            case APR, JUN, SEP, NOV -> 30;
            case FEB -> leapYear ? 29 : 28;
        };
    }

    public static Month fromNumber(int n) {
        for (Month m : values()) if (m.number == n) return m;
        throw new IllegalArgumentException("1-12のみ: " + n);
    }
}
Java
  • 狙い: 表示・番号・日数計算をひとつに集約。

例題2: ロールと権限チェック

public enum Role {
    USER(Set.of("READ")),
    ADMIN(Set.of("READ", "WRITE", "DELETE"));

    private final Set<String> permissions;
    Role(Set<String> permissions) { this.permissions = permissions; }

    public boolean can(String permission) {
        return permissions.contains(permission);
    }
}
Java
  • 狙い: 文字列定数の散乱を防ぎ、権限を型で管理。

例題3: 支払いステータスの状態遷移

public enum PaymentStatus {
    INIT {
        @Override public PaymentStatus next(boolean ok) { return ok ? AUTHED : FAILED; }
    },
    AUTHED {
        @Override public PaymentStatus next(boolean ok) { return ok ? CAPTURED : FAILED; }
    },
    CAPTURED { @Override public PaymentStatus next(boolean ok) { return this; } },
    FAILED   { @Override public PaymentStatus next(boolean ok) { return this; } };

    public abstract PaymentStatus next(boolean ok);
}
Java
  • 狙い: 定数ごとに異なる振る舞いを持たせる(定数ごとのクラス本体)。

すぐ使えるテンプレート

  • 属性つき定数
public enum X {
    A("labelA", 100), B("labelB", 200);
    private final String label; private final int code;
    X(String label, int code) { this.label = label; this.code = code; }
    public String label() { return label; }
    public int code() { return code; }
}
Java
  • 逆引き(コード→enum)
public static X of(int code) {
    for (X x : values()) if (x.code == code) return x;
    throw new IllegalArgumentException("unknown: " + code);
}
Java
  • 定数ごとの振る舞い
public enum Op {
    ADD { @Override public int apply(int a, int b) { return a + b; } },
    MUL { @Override public int apply(int a, int b) { return a * b; } };
    public abstract int apply(int a, int b);
}
Java

実務のコツと落とし穴

  • 明確な責務: 表示・コード・ロジックを enum に集約すると分岐が減る。
  • 外部値取り込み: DBやAPIのコード値は enum のプロパティ+逆引きメソッドで統一。
  • 名前付け: 定数は大文字+アンダースコア。プロパティやメソッドは通常の命名。
  • JSON/DB連携: シリアライズは name()code を使うかを最初に決める。将来変更しやすいのはコード用フィールド。
  • 過剰肥大化を避ける: 大量のロジックは別クラスへ。enumは「定数+小さな振る舞い」に留める。

まとめ

  • enumは“型安全な定数集”+“小さなクラス”として使える。プロパティで意味を持たせ、メソッドで振る舞いを定義する。
  • switch と逆引きメソッドで分岐と変換を統一し、保守性を高める。
  • 定数ごとの振る舞いで「状態遷移」「演算」などもスッキリ書ける。

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