一、Thread.sleep() vs Object.wait()
| 維度 | sleep() | wait() |
| 所屬類別 | Thread (static) | Object (instance) |
| 鎖行為 | 不釋放鎖 | 釋放鎖,進入等待隊列 |
| 喚醒方式 | 時間到期 / interrupt() | notify() / notifyAll() |
| 使用前提 | 任意位置 | 必須在 synchronized 區塊/方法中 |
| 典型用途 | 暫停執行、限流 | 線程協作、生產消費者模式 |
關鍵點:Thread.sleep(0) 觸發 OS 重新調度,讓出 CPU 時間片。
二、HashMap vs Hashtable
| 特性 | HashMap | Hashtable |
| 線程安全 | 非線程安全 (JDK 1.2+) | 同步方法,線程安全 |
| Null 鍵/值 | 允許一個 null key、多個 null value | 不允許 null |
| 效能 | 高(無同步開銷) | 低(全方法同步) |
| 繼承體系 | 實作 Map 介面 | 繼承 Dictionary (舊API) |
| 遍歷方式 | Iterator (fail-fast) | Enumerator + Iterator |
現代替代:多線程環境用 ConcurrentHashMap(分段鎖/CAS,高併發)。
三、throw vs throws
| 關鍵字 | 位置 | 功能 | 異常數量 |
| throw | 方法體內 | 拋出具體異常實例 | 單一 |
| throws | 方法簽名 | 聲明可能拋出的異常類型 | 多個,逗號分隔 |
public void readFile(String path) throws IOException, SQLException {
if (path == null) throw new IllegalArgumentException("路徑不能為空");
// ...
}
四、記憶體溢出 vs 記憶體洩漏
OutOfMemoryError (OOM)
- 請求記憶體超過 JVM 可用上限(
-Xmx)。
- 例子:
List list = new ArrayList<>(); while(true) list.add(new byte[1024*1024]);
Memory Leak
- 物件不再被使用但 GC 無法回收(被 GC Roots 間接引用)。
- 長期積累最終導致 OOM。
四大洩漏類型
- 常發性:每次執行都洩漏(如未關閉的連接、未移除的監聽器)。
- 偶發性:特定條件觸發(如特定輸入導致集合無限增長)。
- 一次性:初始化時洩漏(如靜態集合未清理)。
- 隱式:運行過程持續分配,僅在結束時釋放(如緩存無淘汰策略)。
常見洩漏源與防範
| 洩漏源 | 原因 | 解決方案 |
| 靜態集合 | 生命週期=應用,元素無法回收 | 用 WeakHashMap、定期清理、避免長期持有 |
| 未關閉資源 | Connection/Stream/Thread 持有原生資源 | try-with-resources、finally 關閉 |
| 內部類持有外部引用 | 非靜態內部類隱含 this 參考 | 靜態內部類 + WeakReference |
| 監聽器/回調未移除 | 發布者持有訂閱者引用 | 提供 removeListener、生命週期綁定 |
| ThreadLocal 未清理 | 線程池複用導致值殘留 | 用完 remove()、繼承 ThreadLocalMap 清理 |
五、String / StringBuilder / StringBuilder
| 特性 | String | StringBuffer | StringBuilder |
| 可變性 | 不可變 (final char[]) | 可變 (char[]) | 可變 (char[]) |
| 線程安全 | 是 (不可變天然安全) | 是 (方法 synchronized) | 否 |
| 效能 | 拼接產生大量臨時物件 | 同步開銷較大 | 最高 (單線程首選) |
| 繼承關係 | final class | extends AbstractStringBuilder | extends AbstractStringBuilder |
最佳實踐:單線程用 StringBuilder,多線程用 StringBuffer,常量字串用 String。
六、陣列 vs 鏈表 vs ArrayList vs LinkedList
底層結構對比
| 結構 | 記憶體 | 隨機存取 | 插入/刪除 | 擴容 |
| 陣列 | 連續 (堆/棧) | O(1) | O(n) 需位移 | 固定長度 |
| 鏈表 | 離散 (堆) | O(n) | O(1) 找到位置後 | 動態 |
| ArrayList | 動態陣列 | O(1) | O(n) 含擴容拷貝 | 1.5倍擴容 |
| LinkedList | 雙向鏈表 | O(n) | O(1) 首尾/迭代器位置 | 無擴容 |
選型指南
- 頻繁隨機存取、尾部增刪、元素量穩定 → ArrayList
- 頻繁頭部/中間增刪、無隨機存取、併發迭代 → LinkedList
- 固定大小、極致效能、基本型別 → 陣列
七、面試加分回答技巧
- 結構化表達:定義 → 區別 → 原理 → 應用場景 → 避坑指南。
- 源碼視角:引用關鍵源碼(如
HashMap.put() 擴容邏輯、ThreadLocal 洩漏機制)。
- 實戰案例:結合專案經歷說明如何排查 OOM、優化鎖競爭、選型集合。
- 版本演進:JDK 7/8/11/17 關鍵變更(如 HashMap 紅黑樹、GC 收集器、String 緊湊字串)。
總結
這些高頻題考察的是 Java 核心機制的理解深度。背誦答案不如掌握底層原理:記憶體模型、併發機制、集合源碼、JVM 調優。建議配合 OpenJDK 源碼閱讀、JOL 物件佈局分析、JMH 基準測試,從「知其然」進階到「知其所以然」。
- 上一篇文章: Java 冒泡排序算法原理與實現詳解
- 下一篇文章: Java break 與 continue 關鍵字完全指南
Copyright ©
程式碼之家 All Rights Reserved