7ステップで理解するJavaでの列挙型/enum使用法【改訂版】Eclipseではじめるプログラミング(21)(1/3 ページ)

これからプログラミングを学習したい方、Javaは難しそうでとっつきづらいという方のためのJavaプログラミング超入門連載です。最新のEclipseとJava 6を使い大幅に情報量を増やした、連載「Eclipseではじめるプログラミング」の改訂版となります

» 2011年03月03日 00時00分 公開
[小山博史株式会社ガリレオ]

“列挙”の使いどころは、定数の集合にあり

 例えば、カレンダープログラムを作成したい場合は、1月から12月までをどのようにプログラム上で表現すればいいかを考える必要があります。トランプゲームを作成したい場合は、スーツ(スペード、ハート、ダイヤ、クラブ)について、同様に検討する必要があります。

 こういった「あらかじめ要素数が分かっている定数の集合」を列挙して使うプログラムを作成するには、「列挙型(enumerated type)」の利用を検討するといいでしょう。

 プログラムにおける列挙の表現方法はいくつかありますが、今回は「int enumパターン」「タイプセーフenumパターン」の紹介と、それらよりも使いやすい列挙型について順番に説明します。

 EclipseでJavaプログラミングを始める準備がまだの方は、連載第1回の「Eclipse 3.4で超簡単Javaプログラミング基礎入門」で準備をしておいてください。

【Step 0】カレンダープログラムを考えてみる

 まずは、簡単な機能を持つカレンダープログラムを自作することを想像してみてください。皆さんはどのように1年をプログラム上で表現するでしょうか。

 一番単純な方法は、int型の値を使う表現ですから、1年の各月を表示するとしたら、次のようなプログラムを作ることになるはずです。

package sample21;
 
public class MonthList {
    public void exec() {
        for (int i = 1; i <= 12; i++) {
            System.out.println(i + "月");
        }
    }
  
    public static void main(String[] args) {
        MonthList app = new MonthList();
        app.exec();
    }
}
sample21/MonthList.java
1月
2月
3月
4月
5月
6月
7月
8月
9月
10月
11月
12月
実行結果

【Step 1】文字列の配列で表現してみる

 数値そのままで実現できるような単純なプログラムの場合は、このように簡単に実装できますが、各月の名前を英語で表示したい場合は、どうでしょう。すぐに思いつくのは、文字列の配列を用意して表現する方法かと思います。

 ただしJavaの配列では、添字が0から開始するので、その点に注意が必要です。以下のMonthInEnglishクラスでは、ある月が英語で何というかを表示しています。

package sample21;
 
public class MonthInEnglish {
    private String[] months = new String[] {
       "JANUARY", "FEBRUARY", "MARCH", "APRIL",
       "MAY", "JUNE", "JULY", "AUGUST",
       "OCTOBER", "SEPTEMBER", "NOVEMBER", "DECEMBER",
    };
 
    public void exec() {
        System.out.println("2011年");
        for (int i = 0; i < months.length; i++) {
            String s = (i + 1) + "月";
            System.out.println(s + ":" + months[i]);
        }
    }
 
    public static void main(String[] args) {
        MonthInEnglish app = new MonthInEnglish();
        app.exec();
    }
}
sample21/MonthInEnglish.java
2011年
1月:JANUARY
2月:FEBRUARY
3月:MARCH
4月:APRIL
5月:MAY
6月:JUNE
7月:JULY
8月:AUGUST
9月:OCTOBER
10月:SEPTEMBER
11月:NOVEMBER
12月:DECEMBER
実行結果

【Step 2】Calendarクラスと「int enumパターン」

 ところで、Javaにはカレンダーを表現するクラスは標準で備わってないのでしょうか。実は用意されていて、Javaでカレンダープログラムを作成する場合は、「java.util.Calendar」をよく使います。このクラスでは、月を表現する「JANUARY」などのstaticfinal変数が宣言されているので、これを使うこともできます。

 実際の値は、「JANUARY」は0、「FEBRUARY」は1のようになっています。これらを使うと、例えば、次のようなプログラムが書けます。ここでは、2011年の各月に何日あるかまで表示しています。

package sample21;
 
import java.util.Calendar;
 
public class JavaUtilCalendarMonthList {
    private String[] months = new String[] {
       "JANUARY", "FEBRUARY", "MARCH", "APRIL",
       "MAY", "JUNE", "JULY", "AUGUST",
       "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
    };
    public void exec() {
        System.out.println("2011年");
        for (int i=0 ; i<months.length ; i++) {
            String s = (i+1) + "月";
  
            switch (i) {
            case Calendar.FEBRUARY:
                s = s + ":" + months[i] + "(28日)";
                break;
            case Calendar.APRIL:
            case Calendar.JUNE:
            case Calendar.SEPTEMBER:
            case Calendar.NOVEMBER:
                s = s + ":" + months[i] + "(30日)";
                break;
            case Calendar.JANUARY:
            case Calendar.MARCH:
            case Calendar.MAY:
            case Calendar.JULY:
            case Calendar.AUGUST:
            case Calendar.OCTOBER:
            case Calendar.DECEMBER:
                s = s + ":" + months[i] + "(31日)";
                break;
            }
            System.out.println(s);
        }
    }
    public static void main(String[] args) {
        JavaUtilCalendarMonthList app = new JavaUtilCalendarMonthList();
        app.exec();
    }
}
sample21/JavaUtilCalendarMonthList.java
2011年
1月:JANUARY(31日)
2月:FEBRUARY(28日)
3月:MARCH(31日)
4月:APRIL(30日)
5月:MAY(31日)
6月:JUNE(30日)
7月:JULY(31日)
8月:AUGUST(31日)
9月:SEPTEMBER(30日)
10月:OCTOBER(31日)
11月:NOVEMBER(30日)
12月:DECEMBER(31日)
実行結果

finalで定数変数

 ここで、finalについて説明しておきます。変数をfinalで修飾すると、その変数には一度だけ代入できます。

 例えば、円周率の近似値を3.14として計算で使いたい場合は、PIという変数を用意して、そこへ3.14という値を設定したら変更したくないはずです。こういった変数を用意したいときに、次のように使います。

final double PI = 3.14;

 ちなみに、このように、コンパイル時に定数となる式で初期化された基本データプリミティブjava.lang.String型のfinal変数を「定数変数(constant variable)」といいます。

変数定数のオブジェクト状態は変更可能

 参照型のオブジェクトをfinalで宣言された変数へ代入した場合は、注意が必要です。次のように用意した定数変数finalListに対して、新しいLinkedListのオブジェクトを代入できません。

 つまり「finalList = new LinkedList<String>();」とするとエラーとなります。

final List<String> finalList = new LinkedList<String>();
  
// 次はコメントを外すとエラーとなる
// finalList = new LinkedList<String>();
  
// 次の文は可能
finalList.add("Java");

 これは、finalListに代入された参照値は変更できないからです。しかし、finalListが参照しているオブジェクトの状態は変更できます。つまり、「finalList.add("Java");」のように要素を追加できます。

「int enumパターン(int enum pattern)」

 さて、列挙の話に戻りましょう。JavaUtilCalendarMonthListのように、staticでfinalな変数を使って値を列挙することにより、数値を使うよりもプログラムの可読性が良くなります。

 こういった方法による列挙の表現は、「int enumパターン(int enum pattern)」といわれていて、よく使われています。

 次ページでは、int enumパターンの問題点や「タイプセーフenumパターン」、そして「enum」キーワードと列挙型について解説します。

       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。