早期 Swing getBounds() 返回 Rectangle,頻繁調用導致大量臨時對象分配,GC 壓力劇增。
在組件類中新增細粒度 getter:
public int getX() { return bounds.x; }
public int getY() { return bounds.y; }
public int getWidth() { return bounds.width; }
public int getHeight() { return bounds.height; }
調用端改為:
int x = comp.getX(); // 無新對象分配
int w = comp.getWidth();
Swing 核心操作速度提升 2 倍。代價是 API 膨脹、文檔複雜化,僅建議在性能敏感熱點路徑使用。
public Rectangle getBounds(Rectangle dest) {
dest.x = bounds.x;
dest.y = bounds.y;
dest.width = bounds.width;
dest.height = bounds.height;
return dest;
}
Rectangle reuse = new Rectangle();
for (Component c : components) {
Rectangle r = c.getBounds(reuse); // 同一對象循環複用
// 使用 r...
}
僅適用於可變類(Rectangle、Point、StringBuilder),不可用於 String、BigInteger 等不可變類型。
對外暴露不可變介面,內部使用可變實現,兼顧封裝性與性能:
public class Point { // 不可變
protected final int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
public final int getX() { return x; }
public final int getY() { return y; }
}
public class MutablePoint extends Point { // 僅內部可見
public MutablePoint(int x, int y) { super(x, y); }
public final void setX(int x) { this.x = x; } // 需去掉父類 final 或改用非 final 欄位
public final void setY(int y) { this.y = y; }
}
public class Shape {
private MutablePoint location = new MutablePoint(0, 0);
public Point getLocation() { return location; } // 安全向上轉型
public void move(int dx, int dy) { location.setX(location.getX()+dx); ... }
}
Point,編譯期禁止修改(setX 不可見)MutablePoint,無需創建新對象即可更新座標const Rectangle& 語義,彌補 Java 無 const 引用的缺憾JDK 1.3+ java.math.BigInteger 為不可變公開類,內部大量運算(如 gcd())委派給包私有 MutableBigInteger,避免中間過程創建大量臨時 BigInteger,極大提升大整數運算性能。
| 場景 | 推薦技巧 |
|---|---|
| 頻繁獲取組合對象的單一屬性 | 技巧一:輔助 getter |
| 循環/高頻調用需返回聚合對象 | 技巧二:傳入可變目標對象複用 |
| 領域模型需同時對外不可變、內部高效修改 | 技巧三:不可變/可變雙層類 |