在 Java 开发中,过多的if-else(尤其是嵌套或长链)会导致代码可读性差、维护成本高、扩展性低。以下是系统化的优化方案,从基础重构到设计模式,覆盖不同场景的解决方案:
一、先明确:哪些 if 值得优化?
并非所有if都要消除,以下场景优先优化:
- 长链
if-else if-else(超过 3 层); - 嵌套
if(超过 2 层); - 频繁变更的条件判断(如业务规则、状态流转);
- 重复的条件逻辑(多处出现相同判断)。
二、基础优化:重构现有 if 逻辑
1. 提前 return / 卫语句(消灭嵌套)
将嵌套的if拆解为 “前置判断 + 提前返回”,扁平化代码结构。
反例(嵌套 if) :
public double calculatePrice(User user, Order order) {
double price = order.getBasePrice();
if (user.isVip()) {
if (order.getAmount() > 1000) {
price = price * 0.8; // VIP且金额>1000,8折
} else {
price = price * 0.9; // VIP且金额≤1000,9折
}
} else {
price = price * 1.0; // 非VIP不打折
}
return price;
}
正例(卫语句) :
public double calculatePrice(User user, Order order) {
double price = order.getBasePrice();
if (!user.isVip()) {
return price; // 非VIP直接返回,消灭else
}
return order.getAmount() > 1000 ? price * 0.8 : price * 0.9;
}
2. 合并条件表达式(消除重复判断)
将逻辑上等价的多个条件合并,减少判断次数。
反例:行
if (order.getStatus() == 1 || order.getStatus() == 2 || order.getStatus() == 3) {
// 处理已支付状态
}
正例:
// 1. 用集合封装条件
private static final Set<Integer> PAID_STATUS = Set.of(1, 2, 3);
if (PAID_STATUS.contains(order.getStatus())) {
// 处理已支付状态
}
// 2. 用枚举(更推荐,语义化)
enum OrderStatus {
UNPAID(0), PAID(1), SHIPPED(2), RECEIVED(3);
private final int code;
// 构造器+getter
public static boolean isPaid(OrderStatus status) {
return status == PAID || status == SHIPPED || status == RECEIVED;
}
}
if (OrderStatus.isPaid(order.getStatus())) {
// 处理已支付状态
}
3. 用三元运算符 / Optional 简化简单判断
适用于 “二选一” 的简单逻辑,替代短if-else。
示例 1(三元运算符) :运行
// 反例
String tip;
if (user.getAge() < 18) {
tip = "未成年";
} else {
tip = "成年";
}
// 正例
String tip = user.getAge() < 18 ? "未成年" : "成年";
示例 2(Optional 避免空判断) :
// 反例
if (user != null) {
if (user.getAddress() != null) {
return user.getAddress().getCity();
}
}
return "未知";
// 正例
return Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCity)
.orElse("未知");
三、进阶优化:用数据结构替代 if
1. 映射表(Map):处理 “键 - 逻辑” 映射
适用于根据固定值(如类型、状态)执行不同逻辑的场景,替代if-else if。
场景:根据支付类型(微信、支付宝、银行卡)计算手续费。
反例:运行
public double calculateFee(String payType, double amount) {
if ("WECHAT".equals(payType)) {
return amount * 0.006;
} else if ("ALIPAY".equals(payType)) {
return amount * 0.005;
} else if ("BANK".equals(payType)) {
return amount * 0.008;
}
throw new IllegalArgumentException("无效支付类型");
}
正例(Map + 函数式接口) :
// 1. 定义手续费计算函数
@FunctionalInterface
interface FeeCalculator {
double calculate(double amount);
}
// 2. 初始化映射表(静态常量,仅加载一次)
private static final Map<String, FeeCalculator> FEE_MAP = new HashMap<>();
static {
FEE_MAP.put("WECHAT", amount -> amount * 0.006);
FEE_MAP.put("ALIPAY", amount -> amount * 0.005);
FEE_MAP.put("BANK", amount -> amount * 0.008);
}
// 3. 简化判断逻辑
public double calculateFee(String payType, double amount) {
FeeCalculator calculator = FEE_MAP.get(payType);
if (calculator == null) {
throw new IllegalArgumentException("无效支付类型");
}
return calculator.calculate(amount);
}
2. 枚举:封装状态 / 类型 + 行为
枚举不仅能替代 “值判断”,还能直接封装对应逻辑,比 Map 更类型安全。
场景:同上(支付类型计算手续费),用枚举优化:运行
// 1. 定义枚举,封装行为
enum PayType {
WECHAT(0.006) {
@Override
public double calculateFee(double amount) {
return amount * this.rate;
}
},
ALIPAY(0.005) {
@Override
public double calculateFee(double amount) {
return amount * this.rate;
}
},
BANK(0.008) {
@Override
public double calculateFee(double amount) {
return amount * this.rate;
}
};
protected final double rate;
PayType(double rate) {
this.rate = rate;
}
// 抽象方法,强制每个枚举值实现
public abstract double calculateFee(double amount);
// 辅助方法:根据字符串获取枚举(避免外部判断)
public static PayType from(String payType) {
return PayType.valueOf(payType.toUpperCase());
}
}
// 2. 业务逻辑简化为一行
public double calculateFee(String payType, double amount) {
return PayType.from(payType).calculateFee(amount);
}
四、架构级优化:设计模式
1. 策略模式(Strategy):动态切换算法
适用于 “同一行为有多种实现方式” 的场景(如排序、支付、折扣计算),完全消除条件判断,且易于扩展。
核心结构:
- 抽象策略(Strategy):定义统一接口;
- 具体策略(ConcreteStrategy):实现不同逻辑;
- 上下文(Context):接收策略并执行。
示例(折扣计算) :运行
// 1. 抽象策略
interface DiscountStrategy {
double apply(double amount);
}
// 2. 具体策略
class VipDiscount implements DiscountStrategy {
@Override
public double apply(double amount) {
return amount * 0.8;
}
}
class NewUserDiscount implements DiscountStrategy {
@Override
public double apply(double amount) {
return amount * 0.9;
}
}
class NoDiscount implements DiscountStrategy {
@Override
public double apply(double amount) {
return amount;
}
}
// 3. 上下文(可选,封装策略选择逻辑)
class DiscountContext {
private DiscountStrategy strategy;
// 动态设置策略
public void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
// 执行策略
public double calculate(double amount) {
return strategy.apply(amount);
}
}
// 4. 业务调用(无if)
public void processOrder(User user, double amount) {
DiscountContext context = new DiscountContext();
if (user.isVip()) {
context.setStrategy(new VipDiscount()); // 仅此处少量判断,可结合工厂模式消除
} else if (user.isNewUser()) {
context.setStrategy(new NewUserDiscount());
} else {
context.setStrategy(new NoDiscount());
}
double finalAmount = context.calculate(amount);
}
2. 工厂模式(Factory):配合策略模式消除策略选择的 if
结合工厂模式,可彻底消除 “选择策略” 的if:运行
// 1. 策略工厂
class DiscountFactory {
public static DiscountStrategy getStrategy(User user) {
if (user.isVip()) {
return new VipDiscount();
} else if (user.isNewUser()) {
return new NewUserDiscount();
}
return new NoDiscount();
}
}
// 2. 业务调用(完全无if)
public void processOrder(User user, double amount) {
DiscountStrategy strategy = DiscountFactory.getStrategy(user);
double finalAmount = strategy.apply(amount);
}
3. 状态模式(State):处理状态流转的 if
适用于 “对象状态决定行为” 的场景(如订单状态:待支付→已支付→已发货→已完成),替代大量状态判断的if。
核心思想:将每个状态的行为封装为独立类,状态切换由状态类自身控制。
五、其他补充技巧
- 使用多态:父类定义抽象方法,子类实现不同逻辑,通过多态调用替代
if判断(本质是策略模式的简化)。 - 提取方法:将复杂
if内的逻辑提取为独立方法,即使if仍存在,代码可读性也会提升。 - 避免过度优化:简单的、不变的
if(如 2 层以内)无需强制消除,可读性优先。 - 使用规则引擎:超复杂的业务规则(如风控、优惠券)可引入规则引擎(如 Drools),彻底脱离硬编码的
if。