Effective Java笔记:enum 代替 int 常量

使用 enum(枚举)代替 int 常量是一种更安全、更具可读性和可维护性的编程实践。相比使用 int 常量,enum 提供了更强的类型检查、命名空间管理以及附加信息的能力。


为什么应该用 enum 代替 int 常量?

1. 类型安全
  • int 常量没有类型限制,可以传入任何整数值,容易引发错误。
  • enum 是一种真正的类型,编译器会检查传入的值是否是枚举中定义的合法值。

示例:

// 使用 int 常量
public static final int APPLE = 0;
public static final int BANANA = 1;
public static final int ORANGE = 2;

void printFruit(int fruit) {
    System.out.println(fruit);
}

// 可以传入非法值
printFruit(3); // 编译通过,但逻辑错误

// 使用 enum
enum Fruit {
    APPLE, BANANA, ORANGE
}

void printFruit(Fruit fruit) {
    System.out.println(fruit);
}

// 必须传入合法值
printFruit(Fruit.APPLE); // 正确
printFruit(3); // 编译错误

2. 可读性更强
  • int 常量在调试或日志中显示为数字,难以理解。
  • enum 可以直接显示为有意义的名称。

示例:

System.out.println(Fruit.BANANA); // 输出 BANANA
System.out.println(BANANA);       // 输出 1(如果是 int 常量)

3. 可扩展性
  • enum 可以拥有字段、方法、构造函数,支持更复杂的行为。
  • int 常量只能表示简单的数值。

示例:

enum Planet {
    MERCURY(3.303e+23, 2.439e6),
    VENUS  (4.869e+24, 6.052e6),
    EARTH  (5.976e+24, 6.378e6);

    private final double mass;     // 单位:千克
    private final double radius;   // 单位:米

    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }

    public double getMass() { return mass; }
    public double getRadius() { return radius; }
}

4. 命名空间管理
  • int 常量容易发生命名冲突。
  • enum 有独立的命名空间,避免冲突。

示例:

// int 常量容易冲突
public static final int START = 0;
public static final int STOP = 1;

public static final int RUNNING = 0;
public static final int PAUSED = 1;

// enum 避免冲突
enum Status {
    START, STOP
}

enum State {
    RUNNING, PAUSED
}

5. 支持 switch 语句
  • enum 可以在 switch 语句中使用,增强逻辑表达能力。

示例:

enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

void schedule(Day day) {
    switch (day) {
        case MONDAY:
        case FRIDAY:
            System.out.println("Meeting day");
            break;
        case SATURDAY:
        case SUNDAY:
            System.out.println("Weekend");
            break;
        default:
            System.out.println("Work day");
    }
}

策略枚举

枚举策略类(Enum-based Strategy Pattern) 是一种将枚举(enum)与策略模式(Strategy Pattern)结合使用的编程技巧。它利用枚举的特性来封装不同的行为或策略。

public enum PaymentStrategy {
    ALIPAY {
        @Override
        public void pay(double amount) {
            System.out.println("使用支付宝支付: ¥" + amount);
        }
    },
    WECHAT {
        @Override
        public void pay(double amount) {
            System.out.println("使用微信支付: ¥" + amount);
        }
    },
    UNIONPAY {
        @Override
        public void pay(double amount) {
            System.out.println("使用银联支付: ¥" + amount);
        }
    };

    public abstract void pay(double amount);
}

使用方式:

public class ShoppingCart {
    private PaymentStrategy strategy;

    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void checkout(double amount) {
        strategy.pay(amount);
    }
}

// 测试
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        cart.setPaymentStrategy(PaymentStrategy.ALIPAY);
        cart.checkout(199.9);

        cart.setPaymentStrategy(PaymentStrategy.WECHAT);
        cart.checkout(88.8);
    }
}
带参数的策略
public enum DiscountStrategy {
    NONE(1.0) {
        @Override
        public double applyDiscount(double price) {
            return price * factor;
        }
    },
    TEN_PERCENT_OFF(0.9) {
        @Override
        public double applyDiscount(double price) {
            return price * factor;
        }
    },
    TWENTY_PERCENT_OFF(0.8) {
        @Override
        public double applyDiscount(double price) {
            return price * factor;
        }
    };

    protected final double factor;

    DiscountStrategy(double factor) {
        this.factor = factor;
    }

    public abstract double applyDiscount(double price);
}

使用:

double originalPrice = 100.0;
double discountedPrice = DiscountStrategy.TEN_PERCENT_OFF.applyDiscount(originalPrice);
System.out.println("折扣后价格: ¥" + discountedPrice);
结合 @FunctionalInterface 和 Supplier 等函数式接口进一步简化代码
@FunctionalInterface
public interface PaymentFunction {
    void pay(double amount);
}
定义枚举策略类
public enum PaymentStrategy {
    ALIPAY(amount -> System.out.println("使用支付宝支付: ¥" + amount)),
    WECHAT(amount -> System.out.println("使用微信支付: ¥" + amount)),
    UNIONPAY(amount -> System.out.println("使用银联支付: ¥" + amount));

    private final Consumer<Double> paymentAction;

    PaymentStrategy(Consumer<Double> paymentAction) {
        this.paymentAction = paymentAction;
    }

    public void pay(double amount) {
        paymentAction.accept(amount);
    }
}

使用:

public class ShoppingCart {
    private PaymentStrategy strategy;

    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void checkout(double amount) {
        strategy.pay(amount);
    }
}

// 测试
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        cart.setPaymentStrategy(PaymentStrategy.ALIPAY);
        cart.checkout(199.9);

        cart.setPaymentStrategy(PaymentStrategy.WECHAT);
        cart.checkout(88.8);
    }
}

结果:使用支付宝支付: ¥199.9
     使用微信支付: ¥88.8
使用 Function<Double, Double> 简化折扣策略
定义枚举策略类
public enum DiscountStrategy {
    NONE(price -> price),
    TEN_PERCENT_OFF(price -> price * 0.9),
    TWENTY_PERCENT_OFF(price -> price * 0.8);

    private final Function<Double, Double> discountFunction;

    DiscountStrategy(Function<Double, Double> discountFunction) {
        this.discountFunction = discountFunction;
    }

    public double applyDiscount(double price) {
        return discountFunction.apply(price);
    }
}

使用:

double originalPrice = 100.0;
double discountedPrice = DiscountStrategy.TEN_PERCENT_OFF.applyDiscount(originalPrice);
System.out.println("折扣后价格: ¥" + discountedPrice);

结果:折扣后价格: ¥90.0
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值