今さら聞けないenumの基本を解説

java

enumの「列挙型です」という解説で心が折れた人向けに書いていきます。

enumとは一体何者なのか?使うことのメリットは何なのか??

「列挙型」という煙に巻くような言葉ではなく、enumを使うメリット・使いどころ、そしてenumの使い方が簡単に理解できるように頑張って書いていきたいと思います。

[スポンサーリンク]

enumを使うことのメリット

それではまず、enumを使うことのメリットから考えていきましょう。

こちらのソースを見て下さい。
OKとERRORをそれぞれで定数に持って、checkメソッドで引数とそれぞれの定数を比較して文字列を返却するというものです。

そして、引数がOKとERRORで定義されている値以外がくるとnullを返すようにしています。

    private static int OK = 1;
    private static int ERROR=2;

    private static String check(int i) {
        if (i == OK) {
            return "OKです。";
        } else if (i == ERROR) {
            return "エラーです。";
        }
        return null;
    }
>実行結果
OKです。

ロジックとしては一見するとよさそうですが、イケてないですよね。

イケてない理由としては、

  1. nullを返却したくない場合は、エラー処理を入れなければなりません。
  2. checkメソッドの引数はintになっているので、使う側からは何を指定してよいのか分かりません。

これらのイケてないところを解消してくれるのがenumです。

enumを使うことのメリットの概要は、定義する方も使う方も引数が明確になる。というのがenumを使う最大のメリットです。

次でenumを使うことのメリットについてもう少し詳しく書いていきます。

enumを使うメリット

さて、enumを使うことのメリットをもう少し詳しく書いていきます。

enumを使うことによって、上記のcheckメソッドに1、2以外が指定されることをブロックすることが出来ます。

ようは、メソッド側で1、2以外はダメ!と宣言されていれば、checkメソッドを使う側から見ても仕様が非常に明確ですね。

それではいよいよenumの使い方を解説していきます。

enumの使い方

このページの冒頭で紹介しましたcheckメソッドをenumに置き換えてみます。

ExamplEnumというのがenumです。
ここでは特に1とか2の値は持たせる必要はありません。(値を持たせることもできますが、それはページ後半で解説していきます。)

public class Exampl {

    private enum ExamplEnum {
        OK,
        Error;
    }

    public static void main(String arg[]) {
        String result = check(ExamplEnum.Error);
        System.out.println(result);
    }
 
    private static String check(ExamplEnum examplEnum) {
        if (examplEnum == ExamplEnum.OK) {
            return "OKです。";
        } else if (examplEnum == ExamplEnum.Error) {
            return "Errorです。";
        }
        return null;
    }
}

実行結果

>実行結果
Errorです。

それでは少し解説していきましょう。まずは、checkメソッドの引数を見て下さい。

intの代わりに、ExamplEnumクラスを引数としています。

checkメソッドの引数をintからExamplEnumクラスに変えることで、呼び出し側はどの値を指定すればよいかが明確になりました。

そしてcheckメソッド自身もExamplEnum以外の値が入ってくることを予防することができました。

これらがenumを使うことのメリットですね。

intの値をenumに変換する

さて、上記ではenumの基本的な使い方をみてきました。

でもちょっと実践的ではないですよね。

というのも、webアプリだとリクエストパラメータがenumという場面ってないと思います。

ということは、リクエストパラメータがintだった場合は、一度内部的にこのintの値をenumに変換する必要があります。

intの値をenumに変換すると聞くとこのようなロジックを想像しちゃいますよね。

public class Exampl2 {

    private enum ExamplEnum {
        OK,
        Error;
    }

    public static void main(String arg[]) {
        int param = 1;
        ExamplEnum examplEnum;
        if (param == 1) {
            examplEnum = ExamplEnum.OK;
        } else {
            examplEnum = ExamplEnum.Error;
        }
        System.out.println("enum : " + examplEnum);
    }
}

こんな感じは絶対にダメです。

これではせっかくenumを定義しているのに定数と変わらない使い方になってしまってますね。。

それではどういうのがいいのでしょうか?

こういうケースは、enumは値を持つことができるので、enum自身にintの値を持たせてint値とenum値をマッチングさせるようにしましょう。

上記のソースはこのようにすることができます。

public class Exampl3 {
    private enum ExamplEnum {
        OK(1),
        Error(2);

        private int id;

        public int getId() {
            return id;
        }

        private ExamplEnum (int id) {
          this.id = id;
        }
        
        public static ExamplEnum valueOf(int id) {
            ExamplEnum[] array = values();
            for(ExamplEnum num : array) {
                if (id == num.getId()){
                    return num;
                }
            }
            return null;
        }
    }
    
    public static void main(String arg[]) {
        int param = 1;
        ExamplEnum examplEnum = ExamplEnum.valueOf(param);
        System.out.println("enum : " + examplEnum);
    }
}

このように、enumに値を持たせることができますので、まずは値をもたせましょう。

idというフィールドがenumに持たせたidになります。

このidというフィールドの名前は何でもOKです。

しかし、このidに対してgetメソッドとコンストラクタにidを指定することは必須となりますので気をつけて下さい。

また、valueOfというメソッドが超重要になります。このメソッドがidとenumを紐付けるためのメソッドになります。

このメソッドを作ることによって、29行目のような方法でint値からenumに簡単に変更することができます。

enumに複数の値を持たせる

上記ではenumに値を持たせる方法を紹介しました。

しかし値を複数持たせたい場合はどうすればよいのでしょうか?

ご安心下さい!enumには複数値を持たせることができます。

public class Exampl4 {
    private enum ExamplEnum {
        OK(1, "オッケー"),
        Error(2, "エラー");

        private int id;
        private String name;

        public int getId() {
            return id;
        }
        public String getName() {
            return name;
        }

        private ExamplEnum (int id, String name) {
          this.id = id;
          this.name = name;
        }
        
        public static ExamplEnum valueOf(int id) {
            ExamplEnum[] array = values();
            for(ExamplEnum num : array) {
                if (id == num.getId()){
                    return num;
                }
            }
            return null;
        }
    }
    
    public static void main(String arg[]) {
        int param = 1;
        ExamplEnum examplEnum = ExamplEnum.valueOf(param);
        System.out.println("enum : " + examplEnum.getName());
    }
}

こちらのサンプルコードでは、1つのenumに対して2つのパラメータを指定しています。

ここで気をつけたいことは、1つのパラメータにつき必ずメンバ変数とgetメソッドとコンストラクタへの追加を忘れないようにして下さい。

そして上記の追加したパラメータに対しても、値からenumへ変換することが可能です。
以下ハイライト部分のロジックを作成して、44行目のように呼び出して下さい。

public class Exampl4 {
    private enum ExamplEnum {
        OK(1, "オッケー"),
        Error(2, "エラー");

        private int id;
        private String name;

        public int getId() {
            return id;
        }
        public String getName() {
            return name;
        }

        private ExamplEnum (int id, String name) {
          this.id = id;
          this.name = name;
        }
        
        public static ExamplEnum valueOf(int id) {
            ExamplEnum[] array = values();
            for(ExamplEnum num : array) {
                if (id == num.getId()){
                    return num;
                }
            }
            return null;
        }
        
        public static ExamplEnum valueOfByName(String name) {
            ExamplEnum[] array = values();
            for(ExamplEnum num : array) {
                if (name.equals(num.getName())){
                    return num;
                }
            }
            return null;
        }
    }
    
    public static void main(String arg[]) {
        String param = "オッケー";
        ExamplEnum examplEnum = ExamplEnum.valueOfByName(param);
        System.out.println("enum : " + examplEnum.getName());
    }
}

enumに3つ以上の値を持たせる

上記でenumに2つのパラメータを持たせる方法を紹介しましたが、パラメータはいくつでももたせることができます。
ただし、ここに値をもたせすぎると一体何のためのクラスなのかがわからなくなるのでほどほどにしておきましょう。

public class Exampl4 {
    private enum ExamplEnum {
        OK(1, "オッケー", 10),
        Error(2, "エラー", 20);

        private int id;
        private String name;
        private int status;

        public int getId() {
            return id;
        }
        public String getName() {
            return name;
        }
        public int getStatus() {
            return status;
        }
        
        private ExamplEnum (int id, String name, int status) {
          this.id = id;
          this.name = name;
          this.status = status;
        }
        
        public static ExamplEnum valueOf(int id) {
            ExamplEnum[] array = values();
            for(ExamplEnum num : array) {
                if (id == num.getId()){
                    return num;
                }
            }
            return null;
        }
        
        public static ExamplEnum valueOfByName(String name) {
            ExamplEnum[] array = values();
            for(ExamplEnum num : array) {
                if (name.equals(num.getName())){
                    return num;
                }
            }
            return null;
        }
    }
    
    public static void main(String arg[]) {
        int param = 1;
        ExamplEnum examplEnum = ExamplEnum.valueOf(param);
        System.out.println("enum : " + examplEnum.getStatus());
    }
}

さいごに

以上がenumの基本的な使い方です!

列挙型という言葉を使わずに説明してみましたがいかがでしたでしょうか。

今まで定数をintやStringにしている人は積極的にenumを使うことをオススメします。各メソッドの引数はある程度絞られているほうが読む方としては読みやすいですからね。

それでは!