Java Tips | コレクション:Enum名前一覧

Java Java
スポンサーリンク

Enum名前一覧は「コード上の識別子を“文字列の一覧”として取り出す」技

Enum は「定数の集合」ですが、その一つ一つには「名前(識別子)」があります。
Status.NEWNEW の部分です。

業務では、この「Enum の名前だけ」を一覧で欲しい場面がよくあります。
ログに出したい、設定ファイルに書きたい、外部システムに「有効な値一覧」として渡したい、などです。

ここでは、「Enum の“名前一覧”を安全に取り出すユーティリティ」を、初心者向けにかみ砕いて整理します。


基本:Enum の名前は name() で取れる

まずはシンプルな Enum を用意します。

public enum Status {
    NEW,
    IN_PROGRESS,
    DONE
}
Java

各要素の「名前」は、name() メソッドで取得できます。

Status s = Status.NEW;
System.out.println(s.name()); // NEW
Java

ここで大事なのは、name() が「Enum を宣言したときの識別子そのもの」を返す、という点です。
つまり、ソースコード上の NEWIN_PROGRESSDONE という文字列がそのまま返ってきます。


Enum名前一覧を List<String> で取得する

全要素の名前一覧を取りたいときは、values()name() を組み合わせます。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public final class EnumNames {

    private EnumNames() {}

    public static List<String> namesOfStatus() {
        return Arrays.stream(Status.values())
                     .map(Status::name)
                     .collect(Collectors.toList());
    }
}
Java

使い方はこうなります。

List<String> names = EnumNames.namesOfStatus();
System.out.println(names); // [NEW, IN_PROGRESS, DONE]
Java

ここでの重要ポイントは三つあります。

一つ目は、「Status.values() で全要素を配列として取り出し、それを Arrays.stream で Stream に変換している」ことです。
これで「Enum の全要素を順番に処理する流れ」が作れます。

二つ目は、「map(Status::name) で“Enum → その名前(String)”に変換している」ことです。
Status 型の Stream が、String 型の Stream に変わります。

三つ目は、「collect(Collectors.toList())List<String> にまとめている」ことです。
これで「Enum の名前一覧」が、普通の文字列リストとして扱えるようになります。


汎用ユーティリティにして、どの Enum でも使えるようにする

Status 専用ではなく、「どの Enum にも使える」形にすると、再利用性がぐっと上がります。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public final class EnumNames {

    private EnumNames() {}

    public static <E extends Enum<E>> List<String> namesOf(Class<E> enumType) {
        return Arrays.stream(enumType.getEnumConstants())
                     .map(Enum::name)
                     .collect(Collectors.toList());
    }
}
Java

使い方の例です。

List<String> statusNames = EnumNames.namesOf(Status.class);
// [NEW, IN_PROGRESS, DONE]

List<String> threadStateNames = EnumNames.namesOf(Thread.State.class);
// [NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED]
Java

ここでの重要ポイントは二つです。

一つ目は、「Class<E>#getEnumConstants() で、その Enum 型の全定数を配列として取得している」ことです。
Status.values() と同じ情報ですが、型を引数で受け取れるので汎用化できます。

二つ目は、「map(Enum::name) と書くことで、“どの Enum 型でも name() を呼ぶ”共通処理にしている」ことです。
E が何であっても、Enum である限り name() が呼べます。


名前一覧をどこで使うか:具体的な業務イメージ

例えば、外部設定ファイルに「有効なステータス名だけ書いてよい」という仕様があるとします。
そのとき、「有効な値一覧」をログやエラーメッセージに出したくなります。

String allowed = String.join(", ", EnumNames.namesOf(Status.class));
System.out.println("status は次のいずれかで指定してください: " + allowed);
// status は次のいずれかで指定してください: NEW, IN_PROGRESS, DONE
Java

また、API で「この項目に指定できる値一覧」を返すエンドポイントを作ることもあります。

record EnumOption(String name) {}

List<EnumOption> options =
        EnumNames.namesOf(Status.class).stream()
                 .map(EnumOption::new)
                 .toList();
Java

「Enum の名前一覧」が取れるだけで、こうした「有効値の公開」が簡単になります。


name() と code/label をどう使い分けるか

業務では、Enum に「code」「label」を持たせることが多いです。
そのとき、「name() を外部に出すかどうか」は設計のポイントになります。

name() は「ソースコード上の識別子」なので、
外部仕様として固定してしまうと、「名前を変えたい」ときに互換性問題が起きます。

一方で、「ログやデバッグ用」「内部向けのメッセージ」なら、name() をそのまま使うのは十分アリです。

つまり、

外部インターフェース(API、DB、設定ファイル)には code を使う
内部ログや開発者向けメッセージには name() を使う

という使い分けを意識すると、後々楽になります。
Enum名前一覧ユーティリティは、「内部向けに“今定義されている名前を全部知りたい”」ときに特に役立ちます。


まとめ:Enum名前一覧ユーティリティで身につけてほしい感覚

Enum名前一覧は、
単に「values()name() を知る」話ではなく、
「Enum を“選択肢の定義”として扱い、その識別子一覧を安全に取り出す技」です。

Status.values() から map(Status::name) で名前一覧を作る、という基本パターンを押さえる。
汎用メソッド namesOf(Class<E>) を用意して、どの Enum でも同じ書き方で名前一覧を取れるようにする。
name() は「内部向けの識別子」として使い、外部仕様には code など別の値を使う、という設計を意識する。

あなたのコードのどこかに、
Enum の名前を手書きで列挙している箇所があれば、
それを一度「Enum名前一覧ユーティリティ」に置き換えられないか眺めてみてください。

その小さな整理が、
「Enum を“生きた選択肢定義”として、気持ちよく扱えるエンジニア」への、
確かな一歩になります。

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