直接在類別的 main 中呼叫 getConnection() 多次,返回的 Connection 物件 toString() 顯示相同記憶體位址 (如 com.mysql.jdbc.JDBC4Connection@446cdf90);但經過多層類別間接呼叫則返回不同物件。

getConnection() 內部使用了連線池 (HikariCP, DBCP, C3P0) 或自寫單例快取,同一執行緒、同一參數下會**複用**同一物理連線,toString() 相同是正常行為。DriverManager.getConnection() 都會建立新物理連線,物件位址應不同。若觀察到相同,可能是 JVM 物件回收後記憶體位址被重用 (終結器執行時機不定)。ClassLoader、不同執行緒、或不同連線池實例,導致拿到不同連線物件。Connection c1 = getConnection();
Connection c2 = getConnection();
System.out.println(c1 == c2); // true 表示同一物件引用 (連線池複用)
System.out.println(c1.equals(c2)); // 同理
// 檢查是否為同一物理連線
if (c1.isWrapperFor(com.mysql.cj.jdbc.ConnectionImpl.class)) {
var impl = c1.unwrap(com.mysql.cj.jdbc.ConnectionImpl.class);
println(impl.getThreadId()); // 連線 ID
}
toString() 判斷連線是否相同**,應檢查 == 或連線池統計資訊。maximumPoolSize、idleTimeout。try-with-resources 或 finally { close() } 歸還連線。同一 Connection 物件被重複返回通常是**連線池複用機制**使然,屬正常高效行為;間接呼叫出現不同物件則可能涉及多執行緒/多連線池上下文。理解連線池原理比追蹤物件位址更重要。