Javaでのenum(列挙型)の使い方を学ぶ!文字列や数値の付与の方法。

Javaでのenum(列挙型)の使い方を学ぶ!文字列や数値の付与の方法。

この記事では、Javaにおけるenumの使い方を勉強していく。

enumは使いこなせばコードの読みやすさを向上できるだけでなく、不用意なバグを防ぐことができる。

とはいえ、若干使い方に気をつけるべき部分もあるので注意してみていこう。

enum(列挙型)とは?

enumは英単語”enumeration”の略で列挙を意味する。また、enumは列挙型とも呼ばれる

enumを使用すると並列する関係にある変数をタイプとして定義することができる。

また、Javaにおけるenumはクラスでもあるので、コンストラクタやメソッドを定義することもできる。

enumの使い方

では、Javaにおけるenumの使用方法を見ていこう。

enum AlertLevel {
    INFO("info"),
    WARNING("warning"),
    ERROR("error"),
    FATAL("fata");

    public final String label;

    private AlertLevel(String label) {
         this.label = label;
    }
}


class MainClass {
    public static void main(String[] args) {
        System.out.println(AlertLevel.INFO);
    }
}

enumの定義の方法

enumは複数の定数が集まった特殊なクラスと考えよう。

以下はユーザに対する警告のレベルを定義するenumだ。このようにレベルを定義することによって、レベルにより異なる警告方法やメッセージを定義することが出来る。

enum AlertLevel {
  INFO,
  WARNING,
  ERROR,
  FATAL
}

enumは通常のクラスの中にまとめて書いてもいいし、単体でひとつのファイルにまとめてもいい。

プロジェクトによてルールが決められている場合が多いと思うのが、そうでない場合はenumが使われる範囲を考慮して決定するといいだろう。

enumのデフォルトメソッド

Javaのenumは幾つか便利なデフォルトメソッドを持つ。enumを使いこなすためには必須なので覚えておこう。

values()

定義したすべての値を呼び出すメソッド。staticメソッドなのでインスタンスを生成しなくても使える。

AlertLevel.values()

valueOf()

文字列の引数から該当する値を返すメソッド。こちらもstaticメソッドなのでインスタンスを生成しなくても使える。

AlertLevel alertLevel = AlertLevel.valueOf("INFO");

存在しない値の文字列を渡すとIllegalArgumentExceptionが発生する。

name()

enumの名前を返すメソッド。

AlertLevel newAlert = AlertLevel.INFO;
System.out.println(newAlert.name());

文字列や数値の付与

enumとして定義された値には、文字や数値を付加することもできる。

前章のAlertLevelに文字列を付与する場合を例に見てみよう。

enum AlertLevel {
    INFO("正常に動作しました。"),
    WARNING("注意して下さい。"),
    ERROR("エラーが発生しました。"),
    FATAL("重大なエラーが発生しました。");

    public final String label; // AlertLevelの要素としてlabelというなの文字列を定義している。

    private AlertLevel(String label) { // コンストラクタ。文字列を引数として渡す。
        this.label = label;
    }
}

もちろん複数の要素をenumに付加することもできる。その場合は新しい要素を宣言したうえでコンストラクタを拡張する。

enumのメソッド定義

今までに書いたとおり、enumは一種のクラスなのでメソッドを定義することも可能だ。

ここでは例として、文字列を引数として渡すとその文字列を含むAlertLevelを返すメソッドを作ってみよう。

public static List<AlertLevel> getAlertLevelFromText(String text) {

    ArrayList<AlertLevel> levels = new ArrayList<>();

    for (AlertLevel alertLevel : AlertLevel.values()) { // values()で定義したすべての値を呼び出す。  
        if(alertLevel.label.contains(text)) {
            levels.add(alertLevel);
        }
    }

    return levels;
}

もちろん、メソッドの中身はラムダ式を使ってシンプルに書いてもいいだろう。

return Stream.of(AlertLevel.values()).filter(level -> level.label.contains(text)).collect(Collectors.toList());

enumを使ったSwitch Case

実践においてenumはSwitch構文の分岐条件として使用されることが多い。

AlertLevelを例にしてSwitch構文の例を挙げると以下のようになる。

switch (newAlert) {
    case INFO:
        System.out.println("ログのみを出力する。"); break;
    case WARNING:
        System.out.println("警告メッセージを表示する。"); break;
    case ERROR: case FATAL:
        System.out.println("新しいダイアログにてエラーを表示する。"); break;                
    default:
        System.out.println("エラーログを出力する。");
}

Java 12以降では、switch構文は以下のようにシンプルに書くこともできる。

switch (newAlert) {
    case INFO-> System.out.println("ログのみを出力する。");
    case WARNING -> System.out.println("警告メッセージを表示する。");
    case ERROR, FATAL -> System.out.println("新しいダイアログにてエラーを表示する。");
    default -> System.out.println("エラーログを出力する。");
}