許多團隊在上線前才關注性能,實則性能設計應貫穿架構、接口、編碼全生命周期。事後優化往往只能修補表象,無法解決根本架構缺陷。
對象創建涉及:內存分配、初始化、後續 GC 掃描回收。高頻熱點路徑上,臨時對象是性能殺手。
// 低效:每次調用創建 String
public String match(String inputText) { ... }
// 調用方被迫轉換
String headerLine = new String(buffer, start, end);
String result = matcher.match(headerLine);
class BetterMatcher {
// 原始字符數組
public int match(char[] inputText);
public int match(char[] inputText, int offset, int length);
// 兼容 String
public int match(String inputText);
// 流式處理避免複製
public int match(CharSequence inputText);
}
interface BadMatcher {
String match(String input); // 單一 String 參數
}
interface GoodMatcher {
// 零拷貝訪問
int match(char[] data, int offset, int length);
int match(ByteBuffer buffer);
int match(CharSequence seq);
// 迭代式匹配,避免創建結果對象
int nextMatch();
int getMatchStart();
int getMatchEnd();
String getMatchText(); // 僅在需要時創建
}
// 每次調用創建臨時對象
public Rectangle getBounds() {
return new Rectangle(x, y, width, height); // 臨時對象
}
// 調用方
Rectangle r = component.getBounds();
int w = r.width;
// 方案 1:可變結果對象復用(需文檔說明線程安全)
public void getBounds(Rectangle out) {
out.setBounds(x, y, width, height);
}
// 方案 2:返回基本類型組合
public int[] getBounds() { // 或長度固定的數組
return new int[]{x, y, width, height};
}
// 方案 3:不可變值對象(Java 16+ Record)
public record Bounds(int x, int y, int w, int h) {}
public Bounds getBounds() { return new Bounds(x, y, width, height); }
| 場景 | 避免 | 優選 |
|---|---|---|
| 大量數據排序 | 冒泡/插入排序 O(N²) | Arrays.sort() / TimSort O(N log N) |
| 頻繁查找 | List 線性查找 O(N) | HashMap/HashSet O(1) |
| 重複計算 | 每次現算 | 緩存/記憶化 |
| 字符串拼接 | String + | StringBuilder |
Java 性能設計的本質是減少內存分配壓力、縮短關鍵路徑、最大化數據局部性。優秀的接口設計讓調用方"零成本"使用,而非強迫調用方製造垃圾。這需要架構師在畫類圖時就具備性能意識,而非寫完代碼再找 Profiler 救火。