在 Java 开发历程中,我逐渐积累了一些提升代码质量、开发效率和系统稳定性的实用经验。这些技巧覆盖日常编码、调试调优、工具使用和架构设计等多个层面,希望能帮助你在开发路上少踩坑、多进步。


一、编码规范:写出清晰、易维护的代码

1. 使用 Optional 优雅处理 null

问题:多层对象取值时,频繁的 if (obj != null) 使代码臃肿,易遗漏判断。
建议:使用 Optional 进行链式处理,明确表达空安全逻辑。

java

// 反例
if (user != null && user.getAddress() != null) {
    String city = user.getAddress().getCity();
}

// 推荐写法
String city = Optional.ofNullable(user)
                      .map(User::getAddress)
                      .map(Address::getCity)
                      .orElse("未知城市");

优势:减少嵌套判断,提升代码可读性,有效预防 NullPointerException

2. 使用枚举替代魔法数值

问题:代码中直接使用数字或字符串表示状态,可读性差,维护困难。
建议:通过枚举明确语义,增强类型安全。

java

// 反例
if (orderType == 1) { ... }  // 1 代表什么?难以追溯

// 推荐写法
public enum OrderType {
    NORMAL(1, "普通订单"),
    PRE_ORDER(2, "预售订单");
    // 构造方法、Getter 略
}

if (OrderType.NORMAL.equals(orderType)) { ... }

优势:语义清晰,编译期检查,修改枚举值时可快速定位引用位置。

3. 遵循单一职责原则,拆分复杂方法

建议:每个方法应专注于一个明确的任务,长度建议控制在 50 行以内。

java

// 将复杂流程拆分为多个语义明确的小方法
public void createOrder(OrderRequest request) {
    validateRequest(request);
    calculatePrice(request);
    saveOrder(request);
    sendNotification(request);
}

private void validateRequest(OrderRequest request) {
    // 参数校验逻辑
}

好处:提升可测试性,便于复用与阅读,降低耦合度。


二、调试与性能优化

1. 使用 Assert 进行防御性编程

适用场景:开发阶段的参数校验、状态检查,帮助尽早发现问题。

java

public void deleteUser(Long userId) {
    assert userId != null : "用户ID不能为空";
    // 业务逻辑...
}

注意:生产环境需通过 -ea 参数启用断言,建议结合单元测试使用。

2. 规范日志使用,避免直接输出

推荐做法:使用 SLF4J + Logback 等日志框架,合理设定日志级别。

java

private static final Logger logger = LoggerFactory.getLogger(UserService.class);

// 调试信息使用 debug 级别
logger.debug("用户 {} 查询订单 {}", userId, orderId);

// 错误日志记录完整堆栈
logger.error("订单处理失败,订单ID: {}", orderId, exception);

优势:灵活控制输出内容,避免生产环境输出过多调试信息影响性能。

3. 利用 EXPLAIN 分析 SQL 性能

场景:遇到慢查询时,使用 EXPLAIN 分析执行计划。

sql

EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 'PAID';

关注点

  • type 列:应尽量为 refrange 或 const,避免 ALL(全表扫描)。

  • key 列:确认是否命中索引。


三、高效工具与框架使用

1. 掌握 IDEA 高效快捷键
  • Ctrl + Alt + V:快速提取变量

  • Ctrl + Shift + U:大小写切换

  • Alt + Insert:生成 Getter/Setter/构造函数等

  • Ctrl + Shift + T:快速生成测试类

2. 使用 Arthas 诊断线上问题

Arthas 是阿里开源的 Java 诊断工具,支持动态监控方法执行、查看类加载信息等。

shell

# 查看最繁忙的线程
thread -n 3

# 监测方法调用耗时
watch com.example.service.UserService getUserById '{params, returnObj}' -x 2

适用场景:CPU 飙升、方法执行慢、依赖包冲突等线上问题排查。

3. 实践测试驱动开发(TDD)

建议:在实现功能前先编写测试用例,确保代码可测性与逻辑正确。

java

@Test
void shouldReturnUserWhenGivenValidUserId() {
    User user = userService.getUserById(1L);
    assertNotNull(user);
    assertEquals("admin", user.getUsername());
}

工具组合:JUnit 5 + Mockito,模拟外部依赖,实现隔离测试。


四、常见“坑点”与规避方案

1. 日期时间处理推荐使用 java.time

问题:旧的 Date 和 Calendar 类设计存在缺陷,线程不安全。
推荐:Java 8 引入的 java.time 包。

java

// 获取当前时间(指定时区)
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));

// 格式化输出
String formattedTime = now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
2. 谨慎使用 Arrays.asList()

注意Arrays.asList() 返回的是固定大小的列表,不支持增删操作。

java

List<String> list = Arrays.asList("A", "B", "C");
// list.add("D"); // 抛出 UnsupportedOperationException

// 解决方案:包装为 ArrayList
List<String> editableList = new ArrayList<>(Arrays.asList("A", "B", "C"));
3. 正确使用 @Transactional 注解

常见问题

  • 注解标注在非 public 方法上失效

  • 同类内方法调用不经过代理,事务不生效

java

@Service
public class OrderService {
    
    @Transactional(rollbackFor = Exception.class)
    public void createOrder(Order order) {
        // 主事务逻辑
        orderDao.save(order);
        // 调用内部方法,事务依然有效
        updateInventory(order); 
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateInventory(Order order) {
        // 独立事务逻辑
    }
}

五、架构与设计思维培养

1. 使用策略模式替代复杂条件判断

场景:根据不同类型执行不同业务逻辑(如支付方式、消息通知等)。

java

// 定义策略接口
public interface PaymentStrategy {
    PayResult pay(PaymentRequest request);
}

// 实现具体策略
@Component
public class AlipayStrategy implements PaymentStrategy { ... }

@Component  
public class WechatPayStrategy implements PaymentStrategy { ... }

// 通过上下文选择策略
@Service
public class PaymentContext {
    @Autowired
    private Map<String, PaymentStrategy> strategyMap;
    
    public PayResult executePay(String type, PaymentRequest request) {
        PaymentStrategy strategy = strategyMap.get(type);
        return strategy.pay(request);
    }
}

优势:符合开闭原则,便于扩展新策略,逻辑清晰。

2. 遵循 RESTful API 设计原则

规范示例

方法 路径 说明
GET /users/{id} 获取用户详情
POST /users 创建用户
PUT /users/{id} 更新用户信息
DELETE /users/{id} 删除用户

好处:接口语义明确,前后端协作顺畅,便于生成 API 文档。


六、保持技术敏感度与持续学习

  1. 官方文档优先

  2. 参与技术社区

    • 掘金、InfoQ:获取行业动态与技术实践

    • Stack Overflow:解决具体问题,学习最佳实践

  3. 阅读优质源码
    从常用框架(如 Spring、MyBatis)入手,理解其设计理念与实现机制。


最后一点建议

代码不仅是实现功能的工具,更是表达逻辑思维的艺术。
追求“优雅实现”而不仅仅是“能用就行”,持续打磨细节,这些积累终将转化为你的核心竞争力。

代码的素养,决定开发的高度。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐