列挙型と内部クラス
このレッスンでは、列挙型と内部クラス——Javaの特殊なクラスを学びます。
列挙型
列挙型は固定された定数のセットを定義するために使用されます。
列挙型の定義
JAVA
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
列挙型の使用
JAVA
public class EnumDemo {
public static void main(String[] args) {
Season season = Season.SPRING;
switch (season) {
case SPRING:
System.out.println("春");
break;
case SUMMER:
System.out.println("夏");
break;
case AUTUMN:
System.out.println("秋");
break;
case WINTER:
System.out.println("冬");
break;
}
}
}
列挙型の属性とメソッド
JAVA
public enum Season {
SPRING("春", 1),
SUMMER("夏", 2),
AUTUMN("秋", 3),
WINTER("冬", 4);
private String name;
private int order;
// コンストラクタ
Season(String name, int order) {
this.name = name;
this.order = order;
}
// getter
public String getName() {
return name;
}
public int getOrder() {
return order;
}
}
一般的なenumメソッド
| メソッド | 説明 | 例 |
|---|---|---|
values() |
すべてのenum値 | Season.values() |
valueOf() |
文字列からenumへ | Season.valueOf("SPRING") |
ordinal() |
enumインデックス | Season.SPRING.ordinal() → 0 |
name() |
enum名 | Season.SPRING.name() → "SPRING" |
例:enumメソッド
JAVA
public class EnumMethodDemo {
public static void main(String[] args) {
// すべてのenum値を反復
for (Season s : Season.values()) {
System.out.println(s.ordinal() + ": " + s.getName());
}
// 文字列からenumへ
Season spring = Season.valueOf("SPRING");
System.out.println(spring.getName()); // 春
// enumを比較
System.out.println(Season.SPRING == Season.SPRING); // true
System.out.println(Season.SPRING.equals(Season.SPRING)); // true
}
}
例:曜日enum
JAVA
public enum Weekday {
MONDAY("月曜日", true),
TUESDAY("火曜日", true),
WEDNESDAY("水曜日", true),
THURSDAY("木曜日", true),
FRIDAY("金曜日", true),
SATURDAY("土曜日", false),
SUNDAY("日曜日", false);
private String name;
private boolean isWorkday;
Weekday(String name, boolean isWorkday) {
this.name = name;
this.isWorkday = isWorkday;
}
public String getName() {
return name;
}
public boolean isWorkday() {
return isWorkday;
}
}
public class WeekdayDemo {
public static void main(String[] args) {
for (Weekday day : Weekday.values()) {
String type = day.isWorkday() ? "平日" : "週末";
System.out.println(day.getName() + " - " + type);
}
}
}
内部クラス
内部クラスは別のクラスの内部に定義されたクラスです。
メンバ内部クラス
JAVA
public class Outer {
private int x = 10;
// メンバ内部クラス
public class Inner {
public void show() {
// 外部クラスのprivateメンバーにアクセス可能
System.out.println("x = " + x);
}
}
public void test() {
Inner inner = new Inner();
inner.show();
}
}
public class InnerClassDemo {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.show(); // x = 10
}
}
静的内部クラス
JAVA
public class Outer {
private static int x = 10;
private int y = 20;
// 静的内部クラス
public static class StaticInner {
public void show() {
// 外部クラスの静的メンバーにのみアクセス可能
System.out.println("x = " + x);
// System.out.println("y = " + y); // コンパイルエラー!
}
}
}
public class StaticInnerDemo {
public static void main(String[] args) {
// 外部クラスのオブジェクトを作成する必要がない
Outer.StaticInner inner = new Outer.StaticInner();
inner.show(); // x = 10
}
}
ローカル内部クラス
JAVA
public class Outer {
public void method() {
// ローカル内部クラス:メソッド内に定義
class LocalInner {
public void show() {
System.out.println("ローカル内部クラス");
}
}
LocalInner inner = new LocalInner();
inner.show();
}
}
無名内部クラス
JAVA
public interface Greeting {
void greet(String name);
}
public class AnonymousDemo {
public static void main(String[] args) {
// 無名内部クラス
Greeting hello = new Greeting() {
@Override
public void greet(String name) {
System.out.println("Hello, " + name + "!");
}
};
hello.greet("Alice"); // Hello, Alice!
// Lambda短縮形(関数型インターフェース)
Greeting hi = name -> System.out.println("Hi, " + name + "!");
hi.greet("Bob"); // Hi, Bob!
}
}
例:イベント処理のための無名内部クラス
JAVA
public interface OnClickListener {
void onClick(String button);
}
public class Button {
private String text;
private OnClickListener listener;
public Button(String text) {
this.text = text;
}
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
public void click() {
if (listener != null) {
listener.onClick(text);
}
}
}
public class ButtonDemo {
public static void main(String[] args) {
Button btn = new Button("送信");
// 無名内部クラス
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(String button) {
System.out.println(button + "がクリックされました");
}
});
btn.click(); // 送信がクリックされました
}
}
内部クラスの比較
| タイプ | 場所 | 外部クラスへのアクセス | 作成方法 |
|---|---|---|---|
| メンバ内部クラス | クラス内 | すべてのメンバー | outer.new Inner() |
| 静的内部クラス | クラス内 | 静的メンバー | new Outer.Inner() |
| ローカル内部クラス | メソッド内 | すべてのメンバー + ローカルfinal | メソッド内で作成 |
| 無名内部クラス | 任意の場所 | ローカル内部クラスと同じ | new Interface(){} |
❓ よくある質問
Q いつenumを使用すべきですか?
A 季節、曜日、状態など、固定された定数のセットを定義するとき。
Q いつ無名内部クラスを使用すべきですか?
A 簡単なインターフェース実装、特にイベントコールバックに。Java 8以降、関数型インターフェースにはLambdaが推奨されます。
Q 内部クラスは何に使用されますか?
A コールバックの実装、外部クラスのプライベートメンバーへのアクセス、関連するクラスの整理。
📖 まとめ
- enumは固定された定数を定義し、属性とメソッドを持つことができる
- 内部クラスはメンバ、静的、ローカル、無名に分類される
- 無名内部クラスはLambdaに短縮可能(関数型インターフェース用)
- 一般的なenumメソッド:values、valueOf、ordinal
📝 演習
- 季節enum: 季節名と温度範囲を持つSeason enumを定義
- 状態機械: enumを使用して注文状態(保留、支払い済み、発送済み、完了)を実装
- 無名内部クラス: 無名内部クラスを使用してComparatorソートを実装
次のレッスン
次のレッスンでは、例外処理を学びます — プログラムでのエラー処理方法。



