Tbpgr Blog

元エンジニア 人事 tbpgr(てぃーびー) のブログ

書籍 Effective Java | int定数の代わりにenumを使用する

パンくず

Effective Java
int定数の代わりにenumを使用する

概要

int定数の代わりにenumを使用する

詳細

int enumパターン

特定の数値に意味を持たせて定数化する方法。
この方法に文法的な縛りは何もなく、せいぜい定数名を合わせることで多少分かりやすくする程度だった。
実際にその定数数値に対応した文字列を表示させる方法がなかった。

  /* --- int enumパターン --- */
  /** 言語 Java */
  public static int LANGUAGE_JAVA = 0;
  /** 言語 Ruby */
  public static int LANGUAGE_RUBY = 1;
  /** 言語 PHP */
  public static int LANGUAGE_PHP = 2;
String enumパターン

特定の文字列に意味を持たせて定数化する方法。
こちらは文字列を表示することが可能だが、文字列比較のためパフォーマンスに問題がある。

  /* --- String enumパターン --- */
  /** 言語 Java */
  public static String LANGUAGE_STRING_JAVA = "Java";
  /** 言語 Ruby */
  public static String LANGUAGE_STRING_RUBY = "Ruby";
  /** 言語 PHP */
  public static String LANGUAGE_STRING_PHP = "PHP";
enum

・型安全性が提供されている
名前空間を提供するため、別クラス名・同一変数名の定義が可能
・任意のメソッド、フィールドを追加可能
・valueOfで、Enumの変数名からインスタンスを取得することが可能

enumサンプル・コード仕様

言語enumは数値のコードと言語種別を持つ。
言語種別もEnumで定義され、オブジェクト指向言語手続き型言語などを表す。

数値コードからEnumを取得するメソッドを提供。
DBにEnumに対応するコード値を保持している場合などに重宝する。

特定の言語種別のEnumをListで取得するメソッドを提供。
このようにEnumと関連するメソッドを容易に追加出来るのがenum型のメリット。

enumサンプル・コード

package effective.creation.chapter6;

import java.util.ArrayList;
import java.util.List;

public class SampleNo30 {
  /* --- int enumパターン --- */
  /** 言語 Java */
  public static int LANGUAGE_JAVA = 0;
  /** 言語 Ruby */
  public static int LANGUAGE_RUBY = 1;
  /** 言語 PHP */
  public static int LANGUAGE_PHP = 2;

  /* --- String enumパターン --- */
  /** 言語 Java */
  public static String LANGUAGE_STRING_JAVA = "Java";
  /** 言語 Ruby */
  public static String LANGUAGE_STRING_RUBY = "Ruby";
  /** 言語 PHP */
  public static String LANGUAGE_STRING_PHP = "PHP";

  /** 言語 */
  public enum Language {
    JAVA(0, LanguageType.OBJECT_ORIENTED), RUBY(1, LanguageType.OBJECT_ORIENTED), PHP(2, LanguageType.OBJECT_ORIENTED), SCALA(
        3, LanguageType.FUNCTIONAL), C(4, LanguageType.PROCEDURAL);

    private final int code;
    private final LanguageType type;

    Language(int code, LanguageType type) {
      this.code = code;
      this.type = type;
    }

    /**
     * 言語コードを元に言語を取得する。
     *
     * @param code
     * @return 言語
     */
    public static Language fromIntValue(int code) {
      for (Language eachLanguage : Language.values()) {
        if (eachLanguage.code == code) {
          return eachLanguage;
        }
      }
      throw new IllegalArgumentException();
    }

    /**
     * 言語種別を元に対応する言語のリストを取得する。
     *
     * @param type 言語種別
     * @return 言語リスト
     */
    public static List<Language> getLanguages(LanguageType type) {
      List<Language> languageList = new ArrayList<Language>();
      for (Language eachLanguage : Language.values()) {
        if (eachLanguage.type == type) {
          languageList.add(eachLanguage);
        }
      }
      return languageList;
    }

    public int languageCode() {
      return code;
    }

    public LanguageType languageType() {
      return type;
    }
  }

  /** 言語種別 */
  public enum LanguageType {
    OBJECT_ORIENTED, PROCEDURAL, FUNCTIONAL
  }

  public static void main(String[] args) {
    System.out.println(LANGUAGE_JAVA);
    System.out.println(LANGUAGE_RUBY);
    System.out.println(LANGUAGE_PHP);

    System.out.println("-----------------------------------------------------");

    System.out.println(LANGUAGE_STRING_JAVA);
    System.out.println(LANGUAGE_STRING_RUBY);
    System.out.println(LANGUAGE_STRING_PHP);

    System.out.println("-----------------------------------------------------");

    // 全言語を出力
    for (Language eachLanguage : Language.values()) {
      printLanguageDetail(eachLanguage);
    }

    System.out.println("-----------------------------------------------------");

    // オブジェクト指向言語を出力
    for (Language eachObjectOrientedLanguage : Language.getLanguages(LanguageType.OBJECT_ORIENTED)) {
      printLanguageDetail(eachObjectOrientedLanguage);
    }
    
    System.out.println("-----------------------------------------------------");
    System.out.println(Language.valueOf("JAVA"));

  }

  private static void printLanguageDetail(Language eachLanguage) {
    System.out.print(eachLanguage);
    System.out.print(",");
    System.out.print(eachLanguage.code);
    System.out.print(",");
    System.out.println(eachLanguage.type);
  }
}

出力

0
1
2
-----------------------------------------------------
Java
Ruby
PHP
-----------------------------------------------------
JAVA,0,OBJECT_ORIENTED
RUBY,1,OBJECT_ORIENTED
PHP,2,OBJECT_ORIENTED
SCALA,3,FUNCTIONAL
C,4,PROCEDURAL
-----------------------------------------------------
JAVA,0,OBJECT_ORIENTED
RUBY,1,OBJECT_ORIENTED
PHP,2,OBJECT_ORIENTED