枚举与内部类

本课学习枚举和内部类,了解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;
    }
}

枚举常用方法

方法 说明 示例
values() 所有枚举值 Season.values()
valueOf() 字符串转枚举 Season.valueOf("SPRING")
ordinal() 枚举索引 Season.SPRING.ordinal() → 0
name() 枚举名称 Season.SPRING.name() → "SPRING"

示例:枚举方法

JAVA
public class EnumMethodDemo {
    public static void main(String[] args) {
        // 遍历所有枚举值
        for (Season s : Season.values()) {
            System.out.println(s.ordinal() + ": " + s.getName());
        }
        
        // 字符串转枚举
        Season spring = Season.valueOf("SPRING");
        System.out.println(spring.getName());  // 春天
        
        // 比较枚举
        System.out.println(Season.SPRING == Season.SPRING);  // true
        System.out.println(Season.SPRING.equals(Season.SPRING));  // true
    }
}
▶ 试一试

示例:星期枚举

JAVA
public enum Weekday {
    MONDAY("星期一", true),
    TUESDAY("星期二", true),
    WEDNESDAY("星期三", true),
    THURSDAY("星期四", true),
    FRIDAY("星期五", true),
    SATURDAY("星期六", false),
    SUNDAY("星期日", false);
    
    private String chinese;
    private boolean isWorkday;
    
    Weekday(String chinese, boolean isWorkday) {
        this.chinese = chinese;
        this.isWorkday = isWorkday;
    }
    
    public String getChinese() {
        return chinese;
    }
    
    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.getChinese() + " - " + type);
        }
    }
}
▶ 试一试

内部类

内部类是定义在另一个类内部的类。

成员内部类

JAVA
public class Outer {
    private int x = 10;
    
    // 成员内部类
    public class Inner {
        public void show() {
            // 可以访问外部类的私有成员
            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 什么时候用枚举?
A 定义固定常量集合时,如季节、星期、状态等。
Q 什么时候用匿名内部类?
A 实现接口的简单逻辑,特别是事件回调。Java 8后推荐用Lambda。
Q 内部类有什么用?
A 实现回调机制、访问外部类私有成员、组织相关类。

📖 小节

📝 作业

  1. 季节枚举: 定义Season枚举,包含季节名称和温度范围
  2. 状态机: 用枚举实现订单状态(待付款、已付款、已发货、已完成)
  3. 匿名内部类: 用匿名内部类实现Comparator排序

下一课

下一课我们将学习 异常处理,了解如何处理程序中的错误。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏