我曾经在代码里到处写满了if (status == 1), if (type.equals("A"))这样的判断。直到有一天,产品经理说要把状态“1”的含义从“已下单”改成“待支付”,我差点崩溃。从此,我学会了使用常量类和枚举来消灭“魔法值”。

1. 什么是“魔法值”(Magic Number/String)?

  • 指在代码中突然出现的、未经定义的数字、字符串等。它们的存在使得代码难以理解和维护。
  • 坏味道的代码:
if (order.getStatus() == 1) { // 1 是啥?2又是啥?
    // 处理已支付
} else if (order.getStatus() == 2) {
    // 处理已发货
}

public static final String TYPE_A = "A";
public static final String TYPE_B = "B";

2. 解决方案一:常量类(Interface/Class with Constants)

  • 将魔法值定义为有意义的常量。
public class OrderConstants {
    public static final int STATUS_UNPAID = 1; // 未支付
    public static final int STATUS_PAID = 2;   // 已支付
    public static final int STATUS_SHIPPED = 3; // 已发货
}

// 使用
if (order.getStatus() == OrderConstants.STATUS_PAID) {
    // 逻辑清晰多了!
}

​优点:​​ 简单直观。

​缺点:​​ 类型不安全。你仍然可以传一个99setStatus方法,编译器不会报错。

3. 解决方案二:枚举(Enum)—— 更强大的选择

  • 枚举不仅解决了魔法值问题,还提供了类型安全。
public enum OrderStatus {
    UNPAID, PAID, SHIPPED, DELIVERED
}

public class Order {
    private OrderStatus status; // 类型是OrderStatus,不是int!
    // ... getter setter
}

// 使用
if (order.getStatus() == OrderStatus.PAID) {
    // ...
}

// 编译器会检查,你不能传一个非法的值
// order.setStatus(99); // 编译错误!
order.setStatus(OrderStatus.SHIPPED); // 正确

4. 枚举的高级用法:可以关联属性!

  • 如果状态码在数据库里还是数字,枚举可以完美映射。
public enum OrderStatus {
    UNPAID(1, "未支付"),
    PAID(2, "已支付"),
    SHIPPED(3, "已发货");

    private final int code;
    private final String desc;

    OrderStatus(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    // 根据code获取枚举实例
    public static OrderStatus of(int code) {
        for (OrderStatus status : values()) {
            if (status.code == code) {
                return status;
            }
        }
        return null;
    }
    // ... getters
}

// 从数据库读出的code转换为枚举
OrderStatus status = OrderStatus.of(dbCode);

总结:

告别魔法值,是写出可维护代码的重要一步。对于简单的选项,用常量类;对于有固定范围的、有关联属性的类型,​强烈推荐使用枚举​,它能带来更好的类型安全和代码提示。

如果觉得我的文章对你有用,请随意赞赏