第42章 Java 编码规范与最佳实践

第四十二章 Java 编码规范与最佳实践

“任何傻瓜都能写出计算机能理解的代码,而优秀的程序员写出的是人类能理解的代码。” —— Martin Fowler

想象一下:你打开一个开源项目,满屏都是 a1b2getT() 这样的变量名——恭喜你,你中大奖了,这个项目的维护者可能是个外星人派来的卧底。编码规范听起来像是最无聊的话题,但相信我,没有规范的代码库就像没有交通规则的高速公路——迟早要出车祸。

本章我们就来聊聊 Java 编码的"交通规则",让你的代码不仅能跑,还能让人看得懂、愿意看、甚至想给你点个 Star。


42.1 命名规范

42.1.1 命名的艺术与哲学

命名规范是代码可读性的基石。好的命名就像给变量和函数贴上清晰的功能标签,让后来者一眼就能明白代码想表达什么。反面教材请看:

1
2
3
4
5
// ❌ 令人窒息的操作
int d;           // 时间?距离?难度?
String sb;       // 不知道是什么的字符串
void m() {}      // m 是 method?message?meaning?
Object o;        // 万物皆对象,但你总得告诉我是什么对象吧

而正确打开方式是这样的:

1
2
3
4
5
// ✅ 清新脱俗的命名
int elapsedTimeInSeconds;        // 消逝的时间(秒)
String userEmailAddress;         // 用户邮箱地址
void calculateTotalPrice() {}    // 计算总价
Order pendingOrder;              // 待处理订单

42.1.2 各类命名规范大盘点

Java 中有一份官方的命名约定,称为 Java Naming Conventions(Java 命名约定),来自 Oracle 官方的《Java Language Specification》。但实际上业界还有更多约定俗成的规矩:

元素类型规范示例说明
类名PascalCaseUserService每个单词首字母大写,像人名一样
接口名PascalCaseRunnable常见做法是名词或形容词
方法名camelCasegetUserById()动词或动词短语,小写开头
变量名camelCasemaxRetryCount见名知意,小写开头
常量UPPER_SNAKE_CASEMAX_RETRY_COUNT全部大写,下划线分隔
包名全小写com.example.service公司域名倒写
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 包名示例:域名倒着写
package com.example.order.service;    // ✅ 正确
package com_example_order_service;   // ❌ 像在吃火锅

// 类名和接口名
public class OrderService {}          // ✅ 类:名词
public interface PaymentGateway {}    // ✅ 接口:名词/形容词
public class UserServiceImpl {}       // ✅ 实现类:接口名 + Impl

// 方法名:动宾结构
public void sendEmail() {}            // ✅ 发送邮件
public boolean validateInput() {}     // ✅ 验证输入
public List<Order> findOrdersByUserId(Long userId) {}  // ✅ 带查询条件

// 常量:不能改变的配置值
public static final int MAX_PAGE_SIZE = 100;
public static final String DEFAULT_CHARSET = "UTF-8";

42.1.3 常见命名反模式

变量命名八大戒律

  1. 不要用拼音或无意义字母命名
  2. 不要用单字母(循环计数器 ijk 除外)
  3. 不要用中文拼音缩写(Hzjg = 화장품?化妆品?)
  4. 不要用数字序列(temp1temp2 满天飞)
  5. 不要用类型前缀(strNameiCount 这种 Hungarian Notation 已过时)
  6. 不要用过于通用的词(datainfotemp
  7. 不要用缩写过度(MgrDtl 是什么鬼)
  8. 不要用与关键字冲突的词
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// ❌ 经典反面教材
int n;              // n 是啥?
String str;         // str 可以是任何字符串
List lst;           // lst 是 list?last?lost?
User u;             // u 和 me 是什么关系?
Object o;           // 万物皆空

// ✅ 推荐的替代方案
int customerCount;
String emailAddress;
List<Order> pendingOrders;
User currentUser;
PaymentGateway paymentGateway;

42.1.4 命名词汇表推荐

记不住该用什么词?这里给你一个常用词汇表:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 查询获取用 get/find/load/retrieve
User getUserById(Long id);
List<User> findActiveUsers();
User loadUserProfile(Long id);

// 创建用 create/add/new/register
Order createOrder(Long userId);
void addItemToCart(Long productId);
User registerNewUser(UserDTO dto);

// 更新用 update/modify/change/edit
void updateUserProfile(UserDTO dto);
void modifyOrderStatus(Long orderId, String status);

// 删除用 delete/remove/destroy
void deleteUserById(Long id);
boolean removeFromCart(Long cartItemId);

// 布尔值判断用 is/has/can/should/exists
boolean isEmpty();
boolean hasPermission();
boolean canAccess();
boolean existsUserByEmail(String email);

// 集合用复数或集合名词
List<Order> orders;           // 订单列表
Map<String, User> userMap;    // 用户Map
Set<Role> roles;              // 角色集合

42.2 方法设计原则

42.2.1 方法设计的 SOLID 原则

说到方法设计,就不得不提 SOLID 原则,这是面向对象设计的五大基本原则,由 Robert C. Martin(江湖人称"Bob 大叔")提出。记住这个原则,你的代码想烂都难:

  • S - Single Responsibility Principle(单一职责原则)
  • O - Open/Closed Principle(开闭原则)
  • L - Liskov Substitution Principle(里氏替换原则)
  • I - Interface Segregation Principle(接口隔离原则)
  • D - Dependency Inversion Principle(依赖倒置原则)

42.2.2 单一职责原则(SRP)

一个方法只做一件事,而且把这件事做好。

这个原则听起来简单,但做到的人不多。你的方法可以做很多事,但不能"包揽一切":

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// ❌ 一个方法干了三件事:验证、保存、发送通知
public void saveUserAndSendEmail(User user) {
    // 验证用户信息
    if (user.getEmail() == null || user.getEmail().isEmpty()) {
        throw new IllegalArgumentException("邮箱不能为空");
    }
    // 保存到数据库
    userRepository.save(user);
    // 发送欢迎邮件
    emailService.sendWelcomeEmail(user.getEmail());
}

// ✅ 拆分成三个职责明确的方法
public void saveUser(User user) {
    validateUser(user);
    userRepository.save(user);
}

public void validateUser(User user) {
    if (user.getEmail() == null || user.getEmail().isEmpty()) {
        throw new IllegalArgumentException("邮箱不能为空");
    }
}

public void sendWelcomeEmail(String email) {
    emailService.sendWelcomeEmail(email);
}

42.2.3 方法签名规范

方法签名就像方法的"身份证",好的签名应该让人一眼就知道这个方法是干什么的:

1
2
3
4
5
6
7
8
9
// ✅ 好的方法签名
public User findUserById(Long id);                    // 清晰明了
public List<Order> getOrdersByUserId(Long userId);    // 带上查询条件
public void updateOrderStatus(Long orderId, String newStatus);  // 参数语义明确

// ❌ 让人一头雾水的签名
public User f(Long id);                               // f 是什么?
public List<Order> get(Long userId, Integer type);    // type 是啥意思?
public void update(Long o, String s);                 // 参数名毫无意义

方法命名的"动词库"

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 布尔判断
is + 形容词/状态isEmpty(), isActive(), isValid()
has + 名词hasPermission(), hasChildren(), hasRole()
can + 动词canAccess(), canDelete(), canEdit()
exists + 名词existsUser(), existsOrder()

// CRUD 操作
create + 名词createUser(), createOrder()
update + 名词updateUser(), updatePassword()
delete + 名词deleteUser(), deleteById()
get + 名词getUser(), getOrder()
find + 名词findUser(), findByEmail()

// 批量操作
batch + 动词batchSave(), batchDelete()
bulk + 动词bulkImport(), bulkUpdate()

// 异步操作
async + 动词asyncSendEmail(), asyncProcessOrder()
schedule + 动词scheduleTask(), scheduleReminder()

42.2.4 参数设计原则

方法参数不是越多越好,超过 3 个参数就要警惕了:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// ❌ 参数过多,调用者会疯掉
public Order createOrder(Long userId, String userName, String userEmail,
                         Long productId, String productName, Integer quantity,
                         BigDecimal price, String address, String phone) {
    // ...
}

// ✅ 使用参数对象封装
public Order createOrder(OrderCreateRequest request) {
    // ...
}

// 或者拆分成多个方法调用
public Order createOrder(Long userId, Long productId, Integer quantity, ShippingAddress address) {
    // ...
}

参数对象就像点外卖时的"备注栏",把所有特殊要求集中在一起:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 参数对象:把相关参数打包
public class OrderCreateRequest {
    private Long userId;
    private Long productId;
    private Integer quantity;
    private ShippingAddress shippingAddress;
    private String customerNote;
    private PromoCode promoCode;
}

// 调用时清晰明了
OrderCreateRequest request = new OrderCreateRequest();
request.setUserId(1L);
request.setProductId(100L);
request.setQuantity(2);
request.setShippingAddress(address);
orderService.createOrder(request);

42.2.5 返回值设计原则

返回值也要设计得当,不能含糊其辞:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// ❌ 返回 null 是万恶之源
public User findUserById(Long id) {
    User user = userRepository.findById(id);
    return user;  // 可能返回 null,调用者需要层层判断
}

// ✅ 使用 Optional 明确表示"可能没有"
public Optional<User> findUserById(Long id) {
    return userRepository.findById(id);
}

// 或者返回空集合而不是 null
public List<Order> getUserOrders(Long userId) {
    List<Order> orders = orderRepository.findByUserId(userId);
    return orders != null ? orders : Collections.emptyList();  // 或直接返回空集合
}

// ✅ 布尔返回值要语义清晰
public boolean isUserEligible(Long userId) {
    // 直接返回判断结果,不要玩花样
    return userService.countActiveOrders(userId) < MAX_ORDERS;
}

// ❌ 不要这样返回布尔
public boolean isUserEligible(Long userId) {
    int count = userService.countActiveOrders(userId);
    if (count >= MAX_ORDERS) {
        return false;
    } else {
        return true;
    }
    // 或者更离谱的
    return count < MAX_ORDERS ? true : false;  // 绕了一圈又回到原点
}

42.2.6 方法长度控制

方法应该多长?业界有个流行的说法:一个方法最好不超过 30 行。当然这不是绝对的,但如果你发现一个方法超过了 100 行,那大概率需要重构了:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ❌ 超长方法示例(请勿模仿)
public void processOrder(Long orderId) {
    // 50 行代码... 80 行代码... 150 行代码...
    // 维护者已经哭晕在厕所
}

// ✅ 拆分成多个短小的方法
public void processOrder(Long orderId) {
    Order order = findOrder(orderId);
    validateOrder(order);
    calculateTotal(order);
    deductInventory(order);
    sendNotification(order);
    updateOrderStatus(order);
}

private void validateOrder(Order order) {
    // 验证逻辑,10-20 行
}

private void calculateTotal(Order order) {
    // 计算逻辑,10-20 行
}

42.3 类设计原则

42.3.1 类的单一职责

类的职责也要单一,一个类只负责一块功能:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// ❌ 一个类干了所有事
public class UserManager {
    public void createUser() { /* 创建用户 */ }
    public void sendEmail() { /* 发送邮件 */ }
    public void generateReport() { /* 生成报表 */ }
    public void exportData() { /* 导出数据 */ }
    public void backupDatabase() { /* 备份数据库 */ }
}

// ✅ 职责分离,各司其职
public class UserService {
    public void createUser() { /* 创建用户 */ }
}

public class EmailService {
    public void sendEmail() { /* 发送邮件 */ }
}

public class ReportService {
    public void generateReport() { /* 生成报表 */ }
}

public class DataExportService {
    public void exportData() { /* 导出数据 */ }
}

42.3.2 类与类之间的关系

类不是孤岛,它们之间存在各种关系。了解这些关系有助于设计出良好的代码结构:

  • 依赖关系(Dependency):A 类使用了 B 类
  • 关联关系(Association):A 类持有 B 类的引用
  • 聚合关系(Aggregation):A 由 B 组成,但 B 可以独立于 A 存在
  • 组合关系(Composition):A 由 B 组成,且 B 不能独立于 A 存在
  • 继承关系(Inheritance):A 是 B 的一种
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 依赖关系:方法参数中使用
public class OrderService {
    public void createOrder(OrderCreateRequest request) {
        // OrderService 依赖 OrderCreateRequest
    }
}

// 关联关系:持有引用
public class UserService {
    private UserRepository userRepository;  // 关联关系
    private EmailService emailService;       // 关联关系
}

// 聚合关系:订单聚合了订单项,订单项可以独立存在
public class Order {
    private List<OrderItem> items;  // 聚合关系
}

// 组合关系:订单组合了收货地址,收货地址属于订单
public class Order {
    private ShippingAddress shippingAddress;  // 组合关系
}

// 继承关系
public class Animal {
    public void eat() { }
}

public class Dog extends Animal {  // Dog is-an Animal
    public void bark() { }
}

42.3.3 类的组织结构

一个规范的 Java 类应该有清晰的结构组织:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.example.order.service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

// 类文档注释
/**
 * 订单服务类
 * 负责订单的创建、查询、更新等核心业务逻辑
 *
 * @author JavaMaster
 * @since 2024-01-01
 */
public class OrderService {

    // ========== 常量(静态常量)==========
    public static final int MAX_ITEMS_PER_ORDER = 100;
    private static final BigDecimal FREE_SHIPPING_THRESHOLD = new BigDecimal("99.00");

    // ========== 成员变量(字段)==========
    private OrderRepository orderRepository;
    private UserService userService;
    private PaymentGateway paymentGateway;

    // ========== 构造方法 ==========
    public OrderService(OrderRepository orderRepository,
                        UserService userService,
                        PaymentGateway paymentGateway) {
        this.orderRepository = orderRepository;
        this.userService = userService;
        this.paymentGateway = paymentGateway;
    }

    // ========== 公共方法(API)==========
    public Order createOrder(Long userId, List<Long> productIds) {
        // 1. 验证用户
        User user = userService.findUserById(userId)
                .orElseThrow(() -> new UserNotFoundException(userId));

        // 2. 创建订单
        Order order = new Order();
        order.setUserId(userId);
        order.setStatus(OrderStatus.PENDING);

        // 3. 返回订单
        return order;
    }

    public Optional<Order> findOrderById(Long orderId) {
        return orderRepository.findById(orderId);
    }

    // ========== 私有方法(工具方法)==========
    private void validateOrderItems(List<Long> productIds) {
        if (productIds == null || productIds.isEmpty()) {
            throw new IllegalArgumentException("商品列表不能为空");
        }
        if (productIds.size() > MAX_ITEMS_PER_ORDER) {
            throw new IllegalArgumentException("商品数量超出限制");
        }
    }

    private BigDecimal calculateShippingFee(BigDecimal totalAmount) {
        if (totalAmount.compareTo(FREE_SHIPPING_THRESHOLD) >= 0) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal("10.00");
    }

    // ========== Getter/Setter(如需要)==========
}

42.3.4 类的继承层次

继承是强耦合关系,滥用继承会导致代码僵化。优先使用组合而不是继承:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// ❌ 滥用继承
public class Animal {
    public void eat() { }
    public void sleep() { }
}

public class Dog extends Animal {
    public void bark() { }
}

public class Cat extends Animal {
    public void meow() { }
}

// 问题来了:如果 Dog 和 Cat 都有"抓老鼠"的行为怎么办?
// 在 Animal 里加?那 Bird 也要这个方法吗?
// 在 Dog 和 Cat 里各加一份?代码重复!

// ✅ 使用组合代替继承
public interface Eatable {
    void eat();
}

public interface Sleepable {
    void sleep();
}

public interface Barkable {
    void bark();
}

public class Dog implements Eatable, Sleepable, Barkable {
    private BarkService barkService;

    @Override
    public void eat() { /* 吃 */ }

    @Override
    public void sleep() { /* 睡 */ }

    @Override
    public void bark() {
        barkService.bark();  // 委托给服务
    }
}

42.3.5 不可变类设计

不可变类(Immutable Class)是指实例一旦创建,其状态就不能改变的类。Java 中的 String、BigDecimal、LocalDateTime 都是不可变类。不可变类有诸多好处:线程安全、缓存友好、没有副作用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// ✅ 不可变类示例
public final class OrderStatus {
    private final String code;
    private final String description;

    private OrderStatus(String code, String description) {
        this.code = code;
        this.description = description;
    }

    // 不提供 setter
    // 状态通过静态工厂方法创建

    public static final OrderStatus PENDING = new OrderStatus("PENDING", "待处理");
    public static final OrderStatus PAID = new OrderStatus("PAID", "已支付");
    public static final OrderStatus SHIPPED = new OrderStatus("SHIPPED", "已发货");
    public static final OrderStatus COMPLETED = new OrderStatus("COMPLETED", "已完成");
    public static final OrderStatus CANCELLED = new OrderStatus("CANCELLED", "已取消");

    public String getCode() {
        return code;
    }

    public String getDescription() {
        return description;
    }

    @Override
    public String toString() {
        return code + ":" + description;
    }
}

// 使用
OrderStatus status = OrderStatus.PENDING;
OrderStatus newStatus = OrderStatus.SHIPPED;  // status 不变,返回新实例

42.4 工具推荐

42.4.1 代码格式化工具

Google Java Format

Google 出品的代码格式化工具,一键让代码符合 Google 风格指南:

1
2
3
4
5
# 下载并运行
java -jar google-java-format-1.22.0.jar yourfile.java

# 或者格式化所有 Java 文件
find . -name "*.java" -exec java -jar google-java-format-1.22.0.jar {} \;

Spotless

Spotless 是一个支持多种代码格式规范的插件,特别适合 Maven/Gradle 项目:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!-- Maven pom.xml -->
<plugin>
    <groupId>com.diffplug.spotless</groupId>
    <artifactId>spotless-maven-plugin</artifactId>
    <version>2.43.0</version>
    <configuration>
        <java>
            <googleJavaFormat>
                <version>17</version>
                <style>AOSP</style>
            </googleJavaFormat>
        </java>
    </configuration>
</plugin>

运行 mvn spotless:apply 即可自动格式化代码。

42.4.2 代码静态分析工具

SonarQube

SonarQube 是一个代码质量管理平台,可以检测代码中的 Bug、漏洞、代码异味(Code Smell)和安全问题:

1
2
3
4
5
# Docker 快速启动 SonarQube
docker run -d --name sonarqube -p 9000:9000 sonarqube:latest

# 访问 http://localhost:9000
# 默认账号:admin / admin
1
2
3
4
5
6
<!-- Maven 集成 SonarQube -->
<plugin>
    <groupId>org.sonarsource.scanner.maven</groupId>
    <artifactId>sonar-maven-plugin</artifactId>
    <version>3.11.0</version>
</plugin>

运行 mvn sonar:sonar 即可分析项目。

SpotBugs

SpotBugs 是 FindBugs 的继承者,专门检测 Java 代码中的 Bug:

1
2
3
4
5
6
<!-- Maven 配置 -->
<plugin>
    <groupId>com.github.spotbugs</groupId>
    <artifactId>spotbugs-maven-plugin</artifactId>
    <version>4.8.6</version>
</plugin>

运行 mvn spotbugs:check 进行检查。

Checkstyle

Checkstyle 用于检查代码是否符合编码规范:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!-- Maven 配置 -->
<plugin>
    <groupId>org.apache.rat</groupId>
    <artifactId>apache-rat-plugin</artifactId>
</plugin>

<!-- 或者使用 checkstyle 插件 -->
<plugin>
    <groupId>org.checkstyle</groupId>
    <artifactId>checkstyle-maven-plugin</artifactId>
    <version>3.3.1</version>
</plugin>

42.4.3 IDE 插件推荐

IntelliJ IDEA 插件

插件名称功能
SonarQube集成 SonarQube 分析
CheckStyle-IDEA在 IDE 内检查 Checkstyle 规范
SpotBugs在 IDE 内运行 SpotBugs 分析
MetricsReloaded代码复杂度分析
JProfiler性能分析器

VS Code 扩展

扩展名称功能
Language Support for JavaJava 语言支持
Debugger for Java调试器
Maven for JavaMaven 支持
Checkstyle代码规范检查

42.4.4 代码审查工具

GitHub PR 审查

GitHub 提供了完善的代码审查功能,配合自动化工具效果更佳:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# GitHub Actions 示例:PR 时自动运行 Checkstyle
name: Code Quality Check

on:
  pull_request:
    branches: [ main ]

jobs:
  checkstyle:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
      - name: Run Checkstyle
        run: mvn checkstyle:check

Crucible

Atlassian Crucible 是企业级代码审查工具,支持 Git、SVN、Mercurial 等版本控制系统。

42.4.5 架构可视化工具

PlantUML

PlantUML 让你用代码画架构图,再也不用手动拖拽了:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// PlantUML 类图示例
// 用文本描述类之间的关系
@startuml
class User {
    -Long id
    -String name
    -String email
    +createUser()
    +updateUser()
}

class Order {
    -Long id
    -BigDecimal totalAmount
    +createOrder()
    +cancel()
}

class OrderItem {
    -Integer quantity
    -BigDecimal price
}

User "1" --> "*" Order : places
Order "1" --> "*" OrderItem : contains
OrderItem --> Product : references
@enduml

生成的效果图:

┌─────────────┐         ┌─────────────┐
│    User     │         │   Product   │
├─────────────┤         ├─────────────┤
│ -id         │         │ -id         │
│ -name       │         │ -name       │
│ -email      │         │ -price      │
├─────────────┤         └──────┬──────┘
│ +createUser │                │
│ +updateUser │                │
└──────┬──────┘                │
       │ places                │
       │ 1      *               │
┌──────▼──────┐         ┌──────▼──────┐
│    Order    │         │  OrderItem  │
├─────────────┤         ├─────────────┤
│ -id         │         │ -quantity   │
│ -totalAmount│         │ -price      │
├─────────────┤         └──────┬──────┘
│ +createOrder│                │
│ +cancel()   │                │
└─────────────┘                │
                                │
          *────────────────────┘
          (references)

本章小结

本章我们深入探讨了 Java 编码规范与最佳实践,主要内容包括:

命名规范

  • 类名使用 PascalCase,方法和变量使用 camelCase
  • 常量使用 UPPER_SNAKE_CASE
  • 命名要见名知意,拒绝拼音缩写和单个字母(循环变量除外)
  • 使用统一的命名词汇表:get/find/load、create/update/delete 等

方法设计原则

  • 遵循 SOLID 原则,其中最重要的是单一职责原则
  • 方法名要清晰表达意图,参数控制在 3 个以内
  • 返回 Optional 或空集合而不是 null
  • 方法长度控制在 30 行以内,过长的方法需要拆分

类设计原则

  • 类的职责要单一,每个类只负责一块功能
  • 谨慎使用继承,优先使用组合
  • 合理设计类的组织结构:常量 → 字段 → 构造方法 → 公共方法 → 私有方法
  • 考虑设计不可变类,提高线程安全性

工具推荐

  • 代码格式化:Google Java Format、Spotless
  • 静态分析:SonarQube、SpotBugs、Checkstyle
  • IDE 插件:SonarQube、CheckStyle-IDEA、SpotBugs 插件
  • 代码审查:GitHub PR 审查、Crucible
  • 架构可视化:PlantUML

规范不是束缚,而是自由的基石。就像交通规则让所有人能安全出行一样,代码规范让团队能高效协作。今天养成好习惯,明天少掉头发!

最后修改 March 30, 2026: 新增 Java 教程 (4da1bd7)