首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Effective Java 條目 5:避免創建不必要的對象——實戰解讀

     編輯:Java 綜合教學

核心原則

「優先重用對象而非每次創建新對象。不可變對象天然可重用;可變對象若確不會被修改,也可重用。」

五大避坑場景與優化

1. 字符串字面量 vs new String()

// 反例:每次執行創建新對象
String s = new String("啪啪啪"); // 堆中新對象 + 常量池 "啪啪啪" = 2 個對象

// 正例:複用常量池實例
String s = "啪啪啪"; // 僅 1 個對象,所有相同字面量共享

循環/高頻調用中差異巨大。JDK 1.7+ 常量池移至堆,GC 可回收無引用常量。

2. 靜態工廠方法替代構造器

// 構造器:每次 new
Integer a1 = new Integer("1");
Integer a2 = new Integer("1");
System.out.println(a1 == a2); // false

// valueOf:緩存 -128~127,複用實例
Integer a3 = Integer.valueOf("1");
Integer a4 = Integer.valueOf("1");
System.out.println(a3 == a4); // true

Boolean.valueOf、Long.valueOf 同理。自定義不可變類亦可提供靜態工廠。

3. 重用已知不變的可變對象

反例:每次調用創建新連接

public static Connection getConnection() { // 每次 new
    Class.forName("com.mysql.jdbc.Driver");
    return DriverManager.getConnection(URL, USER, PWD);
}

正例:靜態初始化/單例模式

private static Connection conn;
static {
    Class.forName("com.mysql.jdbc.Driver");
    conn = DriverManager.getConnection(URL, USER, PWD);
}
public static Connection getConnection() { return conn; }

提升性能、簡化邏輯。生產環境建議用成熟連接池(HikariCP/Druid)。

4. Map.keySet() 視圖對象重用

Map<String, Object> map = new HashMap<>();
Set<String> set1 = map.keySet();
map.put("D", "D");
Set<String> set2 = map.keySet();
System.out.println(set1 == set2); // true,同一視圖實例
// 視圖隨 Map 變化自動更新,無需重複創建

5. 自動裝箱陷阱

// 反例:Long 包裝類,循環創建 2^31 個對象
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) sum += i;

// 正例:基本類型 long
long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) sum += i;

一字之差(Long vs long),性能相差數量級。**優先使用基本類型,警惕隱式裝箱**。

辯識觀點:別過度優化

  • 小對象創建/回收在現代 JVM 極廉價(TLAB + 年輕代 GC)
  • 為清晰性創建對象(如 DTO、值對象)通常是好事
  • **自維護對象池** 除非對象極重(DB 連接、線程),否則不如 JVM GC 高效
  • 「當該重用時別創建,當該創建時別重用」——防禦性拷貝、線程安全場景必須新建
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved