本文節選自經典《Java 編程規範》核心章節,聚焦集合存取函數設計、多字段原子訪問、存取函數可見性、靜態字段初始化、局部變量/參數命名與注釋、類/介面/包/編譯單元組織標準,為團隊代碼風格統一、代碼審查、重構治理提供權威參考。
集合 (List/Set/Map/陣列) 比單值字段複雜,需提供粒度化操作而非暴露整個集合引用,以封裝內部結構、支援未來遷移 (如 ArrayList → LinkedList、引入 B 樹)。
| 操作類型 | 命名約定 | 示例 | 語義 |
|---|---|---|---|
| 獲取整個集合 (唯讀視圖) | get<Property>() | getOrderItems() | 返回不可修改視圖或副本 |
| 設置整個集合 (替換) | set<Property>(Collection) | setOrderItems(List) | 清空舊集合、複製新元素 |
| 新增單個元素 | add<ElementType>(Element) | addOrderItem(OrderItem) | 委託內部集合 add |
| 移除單個元素 | remove<ElementType>(Element/Index) | removeOrderItem(item) | 委託內部集合 remove |
| 批次新增 | addAll<ElementType>(Collection) | addAllOrderItems(list) | 批次操作 |
| 批次移除 | removeAll<ElementType>(Collection) | removeAllOrderItems(list) | 批次操作 |
| 建立並新增 | new<ElementType>(參數...) | newOrderItem(productId, qty) | 工廠方法,封裝構建邏輯 |
// 標準實現範例
public class Order {
private final List items = new ArrayList<>();
// 唯讀視圖,防止外部直接修改繞過邏輯
public List getOrderItems() {
return Collections.unmodifiableList(items);
}
public void setOrderItems(List newItems) {
items.clear();
if (newItems != null) items.addAll(newItems);
}
public void addOrderItem(OrderItem item) {
if (item == null) throw new IllegalArgumentException("Item cannot be null");
items.add(item);
item.setOrder(this); // 維護雙向關聯
}
public void removeOrderItem(OrderItem item) {
items.remove(item);
item.setOrder(null);
}
public OrderItem newOrderItem(String productId, int quantity) {
OrderItem item = new OrderItem();
item.setProductId(productId);
item.setQuantity(quantity);
addOrderItem(item);
return item;
}
}
當多字段構成不變量 (如 x/y 坐標必須同時變更、訂單總額 = 明細之和) 時,禁止提供單獨 setter,改為原子更新方法。
public class Shape {
private float x, y;
private float width, height;
private BigDecimal orderTotal;
private List items;
// 正確:原子移動,保證坐標一致性
public void move(float dx, float dy) {
this.x += dx;
this.y += dy;
}
// 錯誤:單獨 setter 破壞不變量
// public void setX(float x) { this.x = x; } // 禁止!
// 內部協作方法:package-private,供 move() 調用
void setPosition(float x, float y) { // 僅內部/同包可見
this.x = x; this.y = y;
}
// 訂單總額:僅由項目操作方法維護,不提供 setter
public BigDecimal getOrderTotal() { return orderTotal; }
// private void setOrderTotal(BigDecimal t) { this.orderTotal = t; } // 私有
public void addItem(OrderItem item) {
items.add(item);
recalcTotal(); // 原子更新總額
}
}
| 場景 | Getter | Setter | 理由 |
|---|---|---|---|
| 普通業務字段 | public | protected/private | 封裝修改邏輯、驗證、事件觸發 |
| 不可變字段 (final) | public | 無 | 建構子初始化,運行期不變 |
| 衍生/計算字段 | public | 無 | 無存儲,動態計算 |
| 集合字段 | public (unmodifiable) | private | 防止外部結構修改 |
| 內部狀態標記 | protected/package | private | 子類/協作類可見,外部不可見 |
| DTO/VO 數據載體 | public | public (或 record) | 無行為、純數據傳輸 |
規則:靜態字段 (類字段) 必須被賦予有效初值,不能假設實例創建前已被初始化。
public class Config {
// 正確:靜態初始化塊/聲明處賦值
private static final String DEFAULT_ENCODING = "UTF-8";
private static final Map CACHE = new ConcurrentHashMap<>();
static {
// 複雜初始化邏輯
CACHE.put("key", loadFromDb());
}
// 錯誤:依賴實例建構子初始化靜態字段
// public Config() { if (CACHE.isEmpty()) init(); } // 多線程不安全、時序不可控
}
customerList、maxRetryCountin/out/inOut (單一輸入輸出) 或 inputStream/outputStream/ioStreami/j/k (傳統、廣泛接受) 或 loopCounter/indexe/ex/exceptionint retryCount = 0; // 重試次數計數器customer、inventoryItemaCustomer、anInputStream、anException —— 區分參數與字段/局部變量,避免名稱遮蔽/** * 根據用戶 ID 查詢訂單 * @param userId 用戶唯一標識,必須 > 0 * @param pageNum 頁碼,從 1 開始,預設 1 * @param pageSize 每頁條數,範圍 [1, 100],預設 20 * @return 訂單分頁結果,非 null * @throws BizException USER_NOT_FOUND 當用戶不存在 */ public PagefindOrders(@Valid @Min(1) Long userId, @Min(1) @Max(100) Integer pageSize) { ... }
List 而非 ArrayList、Map 而非 HashMap、Runnable 而非 ThreadCustomer、OrderItem、FileStreamCollections、Arrays)Exception 結尾:BizExceptionUtils/Helper 結尾:StringUtils/** * 訂單領域實體,封裝訂單生命週期、狀態機、金額計算等核心業務規則。 ** 設計意圖:作為聚合根,保證訂單明細、總額、狀態的一致性。 * 線程安全:非線程安全,需外部同步或單線程訪問。 * 已知限制:不支援分佈式事務,跨服務操作需引入 Saga 模式。 * * @author Zhang San * @version 2.1.0 * @since 1.0.0 * @see OrderItem * @see OrderStatus */ public class Order { ... }
組內按字母序排序,或靜態方法優先、實例方法次之,團隊統一即可。
Runnable、Serializable、Comparable、PaymentServiceint MAX_SIZE = 100; (隱式 public static final)interface Sub extends Super1, Super2 { }接口名 + Impl (如 UserServiceImpl) 或特徵前綴:JdbcUserRepositorycom.company.project.modulecontroller、service、repository、domain、dto、config、exception、utilpackage-private class 封裝模組內部實現規範的本質是降低認知負荷、減少溝通成本、防範潛在缺陷。集合存取函數封裝結構變更、多字段原子操作守護不變量、存取函數可見性最小化、靜態字段確定性初始化、局部變量專用且自註解、參數介面化解耦、類/包命名語義化分層——這些看似瑣碎的細節,累積起來決定了代碼庫的可讀性、可維護性、可演進性。團隊應建立 checkstyle.xml、spotbugs、SonarQube 自動化檢查,將規範內化為工程基因。