【改訂版】Eclipseではじめるプログラミング
連載インデックスへ
【改訂版】Eclipseではじめるプログラミング(21)

7ステップで理解するJavaでの列挙型/enum使用法


株式会社ガリレオ
小山博史
2011/3/3
これからプログラミングを学習したい方、Javaは難しそうでとっつきづらいという方のためのJavaプログラミング超入門連載です。最新のEclipseJava 6を使い大幅に情報量を増やした、連載「Eclipseではじめるプログラミング」の改訂版となります

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


今回の主な内容

“列挙”の使いどころは、定数の集合にあり
【Step 0】カレンダープログラムを考えてみる
【Step 1】文字列の配列で表現してみる
【Step 2】Calendarクラスと「int enumパターン」
【Step 3】クラスで表現する「タイプセーフenumパターン」
「enum」キーワードと列挙型の基礎知識
【Step 4】列挙型で列挙定数を表示する
【Step 5】列挙型を使って日本語でも各月の名前を表示
【Step 6】管理しやすい「java.utilEnumMap」を使う
【Step 7】「java.util.EnumSet」クラスでビット和操作
次回は、Java 5からの肝「アノテーション」

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

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

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

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

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

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

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

  sample21/MonthList.java
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();
}
}

  実行結果
1月
2月
3月
4月
5月
6月
7月
8月
9月
10月
11月
12月

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

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

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

  sample21/MonthInEnglish.java
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();
}
}

  実行結果
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年の各月に何日あるかまで表示しています。

  sample21/JavaUtilCalendarMonthList.java
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();
}
}

  実行結果
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

 Index
第21回 7ステップで理解するJavaでの列挙型/enum使用法
Page1
“列挙”の使いどころは、定数の集合にあり
【Step 0】カレンダープログラムを考えてみる
【Step 1】文字列の配列で表現してみる
【Step 2】Calendarクラスと「int enumパターン」
  Page2
【Step 3】クラスで表現する「タイプセーフenumパターン」
「enum」キーワードと列挙型の基礎知識
【Step 4】列挙型で列挙定数を表示する
  Page3
【Step 5】列挙型を使って日本語でも各月の名前を表示
【Step 6】管理しやすい「java.utilEnumMap」を使う
【Step 7】「java.util.EnumSet」クラスでビット和操作
次回は、Java 5からの肝「アノテーション」

【改訂版】Eclipseではじめるプログラミング バックナンバー 連載インデックスへ»


Java Solution全記事一覧

TechTargetジャパン

Java Solution フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

キャリアアップ

- PR -
@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る
- PR -

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH