第42章 Java 编码规范与最佳实践
第四十二章 Java 编码规范与最佳实践
“任何傻瓜都能写出计算机能理解的代码,而优秀的程序员写出的是人类能理解的代码。” —— Martin Fowler
想象一下:你打开一个开源项目,满屏都是 a1、b2、getT() 这样的变量名——恭喜你,你中大奖了,这个项目的维护者可能是个外星人派来的卧底。编码规范听起来像是最无聊的话题,但相信我,没有规范的代码库就像没有交通规则的高速公路——迟早要出车祸。
本章我们就来聊聊 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》。但实际上业界还有更多约定俗成的规矩:
| 元素类型 | 规范 | 示例 | 说明 |
|---|
| 类名 | PascalCase | UserService | 每个单词首字母大写,像人名一样 |
| 接口名 | PascalCase | Runnable | 常见做法是名词或形容词 |
| 方法名 | camelCase | getUserById() | 动词或动词短语,小写开头 |
| 变量名 | camelCase | maxRetryCount | 见名知意,小写开头 |
| 常量 | UPPER_SNAKE_CASE | MAX_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 常见命名反模式
变量命名八大戒律:
- 不要用拼音或无意义字母命名
- 不要用单字母(循环计数器
i、j、k 除外) - 不要用中文拼音缩写(
Hzjg = 화장품?化妆品?) - 不要用数字序列(
temp1、temp2 满天飞) - 不要用类型前缀(
strName、iCount 这种 Hungarian Notation 已过时) - 不要用过于通用的词(
data、info、temp) - 不要用缩写过度(
Mgr、Dtl 是什么鬼) - 不要用与关键字冲突的词
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 出品的代码格式化工具,一键让代码符合 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 Java | Java 语言支持 |
| Debugger for Java | 调试器 |
| Maven for Java | Maven 支持 |
| 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
规范不是束缚,而是自由的基石。就像交通规则让所有人能安全出行一样,代码规范让团队能高效协作。今天养成好习惯,明天少掉头发!