Skip to content

🔢 枚举与注解

枚举(Enum)

枚举概述

枚举(Enumeration)是一种特殊的类,用于定义一组常量。Java 5 引入了枚举类型。

基本枚举

java
// 定义枚举
public enum Day {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

// 使用枚举
Day today = Day.MONDAY;
System.out.println(today);  // MONDAY

枚举与 switch

java
Day day = Day.MONDAY;

switch (day) {
    case MONDAY:
        System.out.println("星期一");
        break;
    case TUESDAY:
        System.out.println("星期二");
        break;
    // ...
    default:
        System.out.println("其他");
}

枚举方法

java
// 枚举可以定义方法
public enum Day {
    MONDAY("星期一"),
    TUESDAY("星期二"),
    WEDNESDAY("星期三"),
    THURSDAY("星期四"),
    FRIDAY("星期五"),
    SATURDAY("星期六"),
    SUNDAY("星期日");
    
    private final String chineseName;
    
    Day(String chineseName) {
        this.chineseName = chineseName;
    }
    
    public String getChineseName() {
        return chineseName;
    }
}

// 使用
Day day = Day.MONDAY;
System.out.println(day.getChineseName());  // 星期一

枚举方法

java
// 枚举可以定义抽象方法
public enum Operation {
    ADD {
        @Override
        public int calculate(int a, int b) {
            return a + b;
        }
    },
    SUBTRACT {
        @Override
        public int calculate(int a, int b) {
            return a - b;
        }
    },
    MULTIPLY {
        @Override
        public int calculate(int a, int b) {
            return a * b;
        }
    },
    DIVIDE {
        @Override
        public int calculate(int a, int b) {
            return a / b;
        }
    };
    
    public abstract int calculate(int a, int b);
}

// 使用
int result = Operation.ADD.calculate(5, 3);  // 8

枚举常用方法

java
Day day = Day.MONDAY;

// 获取名称
String name = day.name();  // "MONDAY"

// 获取序号
int ordinal = day.ordinal();  // 0

// 比较
boolean equals = day.equals(Day.MONDAY);  // true
int compare = day.compareTo(Day.TUESDAY);  // -1

// 获取所有枚举值
Day[] days = Day.values();
for (Day d : days) {
    System.out.println(d);
}

// 根据名称获取枚举
Day monday = Day.valueOf("MONDAY");

注解(Annotation)

注解概述

注解(Annotation)是 Java 5 引入的特性,用于为代码添加元数据。

内置注解

@Override

java
public class Parent {
    public void method() {
        System.out.println("父类方法");
    }
}

public class Child extends Parent {
    @Override  // 明确表示这是重写方法
    public void method() {
        System.out.println("子类方法");
    }
}

@Deprecated

java
@Deprecated  // 标记为已废弃
public class OldClass {
    @Deprecated  // 标记方法为已废弃
    public void oldMethod() {
        // 旧方法
    }
}

// 使用时会警告
OldClass obj = new OldClass();
obj.oldMethod();  // 编译警告

@SuppressWarnings

java
@SuppressWarnings("unchecked")  // 抑制警告
public void method() {
    List list = new ArrayList();  // 不会警告
    list.add("item");
}

自定义注解

java
// 定义注解
@Target(ElementType.METHOD)  // 只能用于方法
@Retention(RetentionPolicy.RUNTIME)  // 运行时保留
public @interface MyAnnotation {
    String value() default "default";
    int count() default 0;
}

// 使用注解
public class MyClass {
    @MyAnnotation(value = "test", count = 5)
    public void method() {
        // 方法体
    }
}

注解元素

java
// 定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
    String name();
    String email();
    String date();
}

// 使用注解
public class MyClass {
    @Author(name = "张三", email = "zhangsan@example.com", date = "2024-01-01")
    public void method() {
        // 方法体
    }
}

元注解

@Target

java
@Target(ElementType.METHOD)  // 只能用于方法
public @interface MethodAnnotation { }

@Target({ElementType.METHOD, ElementType.FIELD})  // 可用于方法和字段
public @interface MethodOrFieldAnnotation { }

@Retention

java
@Retention(RetentionPolicy.SOURCE)   // 编译时丢弃
@Retention(RetentionPolicy.CLASS)   // 类加载时丢弃
@Retention(RetentionPolicy.RUNTIME)  // 运行时保留
public @interface MyAnnotation { }

@Documented

java
@Documented  // 包含在 JavaDoc 中
public @interface MyAnnotation { }

@Inherited

java
@Inherited  // 可以继承
public @interface MyAnnotation { }

注解处理器

java
// 使用反射处理注解
public class AnnotationProcessor {
    public static void processAnnotations(Class<?> clazz) {
        // 获取类上的注解
        if (clazz.isAnnotationPresent(Author.class)) {
            Author author = clazz.getAnnotation(Author.class);
            System.out.println("作者: " + author.name());
            System.out.println("邮箱: " + author.email());
        }
        
        // 获取方法上的注解
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(Author.class)) {
                Author author = method.getAnnotation(Author.class);
                System.out.println("方法: " + method.getName());
                System.out.println("作者: " + author.name());
            }
        }
    }
}

完整示例

java
// 枚举示例
public enum Status {
    PENDING("待处理"),
    PROCESSING("处理中"),
    COMPLETED("已完成"),
    FAILED("失败");
    
    private final String description;
    
    Status(String description) {
        this.description = description;
    }
    
    public String getDescription() {
        return description;
    }
}

// 注解示例
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String level() default "INFO";
    String message() default "";
}

// 使用
public class Task {
    private Status status = Status.PENDING;
    
    @Log(level = "INFO", message = "开始处理任务")
    public void start() {
        status = Status.PROCESSING;
    }
    
    @Log(level = "INFO", message = "完成任务")
    public void complete() {
        status = Status.COMPLETED;
    }
    
    public Status getStatus() {
        return status;
    }
}

// 使用示例
public class EnumAnnotationExample {
    public static void main(String[] args) {
        // 枚举使用
        Status status = Status.PENDING;
        System.out.println(status.getDescription());  // 待处理
        
        // 遍历枚举
        for (Status s : Status.values()) {
            System.out.println(s + ": " + s.getDescription());
        }
        
        // 注解处理
        Task task = new Task();
        processAnnotations(task.getClass());
    }
    
    private static void processAnnotations(Class<?> clazz) {
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(Log.class)) {
                Log log = method.getAnnotation(Log.class);
                System.out.println("方法: " + method.getName());
                System.out.println("日志级别: " + log.level());
                System.out.println("日志消息: " + log.message());
            }
        }
    }
}

最佳实践

1. 枚举用于固定常量集

java
// ✅ 好的做法:使用枚举定义固定常量集
public enum Color {
    RED, GREEN, BLUE
}

// ❌ 不好的做法:使用常量类
public class Color {
    public static final String RED = "red";
    public static final String GREEN = "green";
    public static final String BLUE = "blue";
}

2. 注解用于元数据

java
// ✅ 好的做法:使用注解添加元数据
@Deprecated
public void oldMethod() { }

// ✅ 好的做法:使用注解标记功能
@Transactional
public void saveData() { }

下一步

掌握了枚举与注解后,可以继续学习:


💡 提示:枚举和注解是 Java 的重要特性,合理使用可以提高代码的可读性和可维护性