JavaでのEnumの実装の仕方と、よく使用するメソッド

はじめに

こんにちは。新卒1年目の岡崎です。エキサイトホールディングス Advent Calendar 2023の21日目を担当します。

よろしければ他の記事もどうぞ!

qiita.com

最近の業務ではEnumを使って実装をしました。なので、今日は改めてJavaEnumについて紹介していきたいと思います。

環境

openjdk version "17.0.2" 2022-01-18
OpenJDK Runtime Environment Temurin-17.0.2+8 (build 17.0.2+8)
OpenJDK 64-Bit Server VM Temurin-17.0.2+8 (build 17.0.2+8, mixed mode)

Enumの実装

Enumは、「列挙型」と呼れています。

Enumの基本的な実装は以下のようになります。

public enum BookType {
    SF(1, "SF"),
    ESSAY(2, "エッセイ"),
    HISTORY(3, "歴史")
    ;

    // フィールドの定義を行う
    private final Integer id;
    private final String type;

    // コンストラクタの定義を行う
    BookType(final Integer id, final String type) {
        this.id = id;
        this.type = type;
    }
}

また、フィールド・コンストラクタの定義をせずに実装することもできます。

public enum BookType {
    SF,
    ESSAY,
    HISTORY
    ;
}

Enumで用意されているメソッド

JavaEnumではさまざまなメソッドが用意されていますが、その中でも私がよく使うメソッドを3つ紹介します。

name

name()では、Enumで定義したオブジェクトの名前を、宣言された通りに返します。

public class Main {
    public static void main(String[] args) throws Exception {
        String name = BookType.ESSAY.name();
        
        System.out.println(name);
    }
}

結果

ESSAY

values

values() では、Enumで定義したオブジェクトを全て返します。

public class Main {
    public static void main(String[] args) throws Exception {
        BookType[] list = BookType.values();
        
        Arrays.stream(list)
        .forEach(bookType -> System.out.println(bookType));
    }
}

結果

SF  

ESSAY  

HISTORY  

valueOf

valueOfでは、引数で指定した文字列から、Enumで定義したオブジェクトを取得できます。

public class Main {
    public static void main(String[] args) throws Exception {
        BookType essay = BookType.valueOf("ESSAY");
        System.out.println(essay);
    }
}

結果

ESSAY

もし、引数で指定した文字列からEnumで定義したオブジェクトを取得できなかった場合、IllegalArgumentExceptionが返ります。

public class Main {
    public static void main(String[] args) throws Exception {
        BookType essay = BookType.valueOf("AAA");
        System.out.println(essay);
    }
}

結果

Exception in thread "main" java.lang.IllegalArgumentException: No enum constant Main.BookType.AAA
    at java.base/java.lang.Enum.valueOf(Enum.java:273)
    at Main$BookType.valueOf(Main.java:9)
    at Main.main(Main.java:5)

補足: Enumを使わなかった実装と、Enumを使った実装の比較

ここまで、Enumの実装の仕方と、よく使用するメソッドを3つ紹介しました。
それでは、補足としてEnumを使わなかった実装と使った実装を比較します。

前提として、IDから本のタイプを取得するようにします。

まずは、Enumを使わなかった場合の実装例です。

public class Main {
    public static void main(String[] args) throws Exception {
        final String type = getBookType(1);
        System.out.println(type);
    }
    
    private static String getBookType(Integer id) {
        if (id.equals(1)) {
            return "SF";
        }
        
        if (id.equals(2)) {
            return "歴史";
        }
        
        if (id.equals(3)) {
            return "エッセイ";
        }
        
        return "";
    }
}

結果

SF

これを、Enumで実装すると以下のようになります。

// Enumに加える実装です

    static Map<Integer, BookType> map = Arrays.stream(BookType.values())
        .collect(
            Collectors.toMap(
                booktype -> booktype.id,
                booktype -> booktype
            )
        );

    public String getType() {
        return type;
    }
    
    public BookType getBookTypeById(Integer id) {
        return map.get(id);
    }
public class Main {
    public static void main(String[] args) throws Exception {
        BookType type = BookType.getBookTypeById(1);
        System.out.println(type.getType());
    }
}

結果

SF

このようにEnumを使うと、変数を代入する場所を限定することができたり、少ない行数で実装することができます。
これにより、可読性の向上や実装ミスを減らすことが期待できます。

最後に

今回は、JavaでのEnumの実装の仕方と、よく使用するメソッドを3つ紹介しました。Enumは上手く使うと、楽に実装をすることができます。ぜひ使ってみてください。