跳转至

15 枚举与注解

本章目标

  • 掌握枚举:定义一组固定常量
  • 掌握枚举的字段、方法、switch 配合
  • 掌握常用注解
  • 了解自定义注解

15.1 什么是枚举?

枚举(enum) 用来定义一组固定取值的常量。比如方向、颜色、生物群系、武器类型。

public enum Direction {
    NORTH, SOUTH, EAST, WEST
}

// 使用
Direction dir = Direction.NORTH;
System.out.println(dir);     // NORTH

对比:

// 用 int 常量(不好):容易传错、无类型检查
int NORTH = 0, SOUTH = 1;
int dir = 100;               // 随便传,没人拦

// 用枚举(好):类型安全
Direction dir = Direction.NORTH;   // 只能选这四个

15.2 枚举的字段与方法

枚举可以带字段、构造器、方法:

public enum ToolType {
    SWORD("剑", 8),
    PICKAXE("镐", 5),
    AXE("斧", 9),
    HOE("锄", 2);

    private final String displayName;
    private final int baseDamage;

    // 构造器(private,外部不能 new)
    ToolType(String displayName, int baseDamage) {
        this.displayName = displayName;
        this.baseDamage = baseDamage;
    }

    public String getDisplayName() { return displayName; }
    public int getBaseDamage() { return baseDamage; }
}

// 使用
ToolType t = ToolType.SWORD;
System.out.println(t.getDisplayName());   // 剑
System.out.println(t.getBaseDamage());    // 8

15.3 枚举常用方法

ToolType[] all = ToolType.values();      // 所有枚举值数组
ToolType t = ToolType.valueOf("SWORD");  // 字符串转枚举(没有会抛异常)
int index = ToolType.SWORD.ordinal();    // 序号(从 0 开始),慎用
String name = ToolType.SWORD.name();     // "SWORD"

switch 配合枚举

switch (t) {
    case SWORD -> System.out.println("近战武器");
    case PICKAXE -> System.out.println("挖矿工具");
    case AXE -> System.out.println("砍树工具");
    default -> System.out.println("其他");
}

switch 枚举不需要写枚举名

枚举在 switch case 里直接写值(case SWORD),不用 case ToolType.SWORD。

15.4 模组里的枚举

// 模组常见:注册表分类
public enum ModTabs {
    BUILDING("建筑方块"),
    MACHINES("机器"),
    TOOLS("工具武器");

    private final String label;
    ModTabs(String label) { this.label = label; }
    public String getLabel() { return label; }
}

// Forge 里很多地方用枚举或类似模式:
// - CreativeModeTab 分组
// - 方块/物品的 Rarity(EPIC、RARE 等)
// - 游戏模式 GameType(SURVIVAL、CREATIVE...)

15.5 注解(Annotation)

注解是给代码打的"标签",给编译器或框架提供信息。以 @ 开头。

常用内置注解

@Override            // 表示重写父类方法,编译器帮你检查
@Deprecated         // 标记过时,调用处会有警告
@SuppressWarnings("unchecked")   // 压制警告(慎用)

元注解:给注解用的注解

@Target(ElementType.METHOD)      // 这个注解能标在哪里(方法/类/字段…)
@Retention(RetentionPolicy.RUNTIME)  // 保留到什么时候(源码/字节码/运行时)
public @interface MyAnnotation {
}
  • @Target:作用位置(TYPE 类、FIELD 字段、METHOD 方法、PARAMETER 参数)
  • @Retention:RUNTIME 才能被反射读取(第 19 章)

自定义注解示例

// 自定义注解:标记一个方法是否需要管理员权限
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireAdmin {
    boolean value() default true;    // 可以带参数和默认值
}

// 使用
public class Commands {
    @RequireAdmin
    public void banPlayer(String name) { ... }

    @RequireAdmin(false)
    public void help() { ... }
}

15.6 Forge 里的注解(模组必见)

// Forge 模组主类注解
@Mod("ffsmod")                          // 声明模组 ID
public class FfsMod {
    public static final String MODID = "ffsmod";
}

// 物品/方块注册(注册表对象注解)
@Mod.EventBusSubscriber(modid = FfsMod.MODID)
public class ModEvents {
    @SubscribeEvent                       // 事件处理方法
    public static void onPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) { ... }

    @OnlyIn(Dist.CLIENT)                  // 仅客户端
    public static void clientInit() { ... }
}

理解注解后,你就知道模组代码里那些 @Mod、@SubscribeEvent、@OnlyIn 是干什么的了——它们给 Minecraft/Forge 框架提供了"在哪里、做什么"的信息。

15.7 小练习

  1. 定义枚举 Weekday(周一到周日),每个带中文名,switch 输出"工作日/周末"
  2. 定义枚举 Rarity(COMMON/RARE/EPIC),带颜色代码字段
  3. 自定义注解 @LogTime(标记方法,RUNTIME 保留),标在两个方法上

本章小结

  • 枚举:固定取值集合,类型安全,可带字段方法
  • switch + 枚举是绝配
  • 注解:给代码打标签,供编译器/框架使用
  • Forge 的 @Mod / @SubscribeEvent 都是注解

下一章:16 Lambda 与 Stream

🏠 返回总站