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

115 道 Java 面試題精選(上):OOP、核心特性、集合、GC 全景解析

     編輯:Java 綜合教學

第一部分:面向對象編程(OOP)核心

Q1: OOP 四大特性?

封裝:隱藏內部狀態,提供公共方法訪問(private + getter/setter)。
繼承:子類復用父類屬性方法,extends 單繼承。
多態:同一接口不同實現,編譯時多態(重載)、運行時多態(重寫)。
抽象:提取共性行為定義接口/抽象類,屏蔽實現細節。

Q2: 封裝優點?

  • 保護對象完整性(校驗邏輯集中)。
  • 降低耦合,實現細節變更不影響調用者。
  • 便於單元測試與維護。

Q3: 抽象類 vs 接口(JDK 8 後)?

維度抽象類接口
方法實現可有抽象/具體方法默認所有方法抽象;JDK8+ 可有 default/static 方法
繼承關係單繼承多實現
構造器有(子類調用)無
字段任意修飾符默認 public static final
設計意圖"is-a" 強關係,共享代碼"has-a" 能力擴展,契約規範

Q4: 為什麼 Java 不支持多繼承?

避免「菱形繼承」二義性問題(兩個父類有同名方法,子類調用歧義)。通過接口多實現替代,JDK8 default 方法衝突需顯式重寫解決。

第二部分:Java 核心特性高頻題

Q5: JVM / JRE / JDK 區別?

  • JVM:執行字節碼的虛擬機,屏蔽底層差異,實現「一次編譯,到處運行」。
  • JRE:JVM + 核心類庫(rt.jar),運行 Java 程序的最小環境。
  • JDK:JRE + 編譯器(javac)、調試器(jdb)、文檔工具(javadoc)等開發工具。

Q6: static 關鍵字含義?能否重寫 static 方法?

  • 屬於類而非實例,類加載時初始化,所有實例共享。
  • 不能重寫:static 綁定在編譯期(靜態綁定),重寫基於運行期動態綁定。子類同名 static 方法叫「隱藏」。

Q7: 能在 static 方法中訪問非 static 變量嗎?

不能。static 階段非 static 變量尚未創建(需實例化後才存在)。

Q8: 八大基本類型與自動拆裝箱?

基本類型包裝類大小
byteByte1 字節
shortShort2 字節
intInteger4 字節
longLong8 字節
floatFloat4 字節
doubleDouble8 字節
booleanBoolean1 位(實際 1 字節)
charCharacter2 字節
  • 自動裝箱:基本類型 → 包裝類(Integer i = 10 實為 Integer.valueOf(10))。
  • 自動拆箱:包裝類 → 基本類型(int n = i 實為 i.intValue())。
  • 緩存範圍:Integer 緩存 -128~127,Long 同理,超出範圍新建對象。

Q9: 重載 vs 重寫?

特性重載重寫
位置同一類父子類
方法名相同相同
參數列表必須不同必須相同
返回類型可不同兼容(协變)
權限修飾符無限制不能更嚴格
綁定時機編譯期運行期

Q10: 構造函數、重載、複製構造函數?

  • 構造函數:創建對象時調用,無返回類型,名同類名。
  • 構造函數重載:參數列表不同的多個構造函數。
  • Java 無複製構造函數(C++ 有),需手寫 new Obj(obj) 或實現 Cloneable。

Q11: 值傳遞 vs 引用傳遞?Java 是哪種?

Java 只有值傳遞。
基本類型:傳值副本。
引用類型:傳引用的副本(指向同一對象),方法內修改對象內容可見,但無法改變實參引用指向。

第三部分:Java 線程與併發

Q12: 進程 vs 線程?

  • 進程:資源分配單位,獨立地址空間。
  • 線程:CPU 調度單位,共享進程內存,輕量級。

Q13: 創建線程三種方式?推薦哪種?

  1. extends Thread
  2. implements Runnable ✅ 推薦:避免單繼承限制,邏輯與線程控制分離。
  3. ExecutorService 線程池 ✅ 生產首選:復用線程、控制併發、管理生命周期。

Q14: 線程六大狀態?

NEW → RUNNABLE → (RUNNING) → BLOCKED/WAITING/TIMED_WAITING → TERMINATED
     就緒      運行中           阻塞/等待/超時等待              死亡

Q15: synchronized 方法 vs 同步塊?

  • 同步方法:鎖對象為 this(實例方法)或 Class 對象(靜態方法),粒度粗。
  • 同步塊:synchronized(obj) { } 可指定任意對象為鎖,粒度細,性能優。

Q16: 死鎖條件與預防?

四條件:互斥、請求保持、不可剝奪、循環等待。
預防:統一加鎖順序(如按對象 hashCode 排序),打破循環等待。

Q17: 如何確保 N 線程訪問 N 資源不死鎖?

強制所有線程按固定順序獲取鎖(如資源 ID 升序)。

第四部分:Java 集合框架深度

Q18: 集合頂層接口?

  • Collection → List(有序、可重復)、Set(無序、唯一)。
  • Map:鍵值對,Key 唯一。

Q19: 為什麼集合接口不直接實現 Cloneable/Serializable?

具體實現決定存儲方式(數組/鏈表/紅黑樹/哈希表)、是否允許重複、是否有序。接口不強制實現細節,由子類決定。

Q20: Iterator 模式與 fail-fast?

  • Iterator 統一遍歷接口,支持 remove()。
  • fail-fast:java.util 集合,遍歷中結構修改拋 ConcurrentModificationException。
  • fail-safe:java.util.concurrent 集合,遍歷副本,不拋異常。

Q21: Iterator vs ListIterator?

特性IteratorListIterator
適用CollectionList
方向單向雙向
功能遍歷、刪除+增、改、索引查詢

Q22: HashMap 底層原理(JDK 8)?

  • 數組 + 鏈表 + 紅黑樹(鏈表長度 >8 且數組長度 >64 轉樹)。
  • put():hash(key) → 索引 → 遍歷鏈表/樹比較 equals() → 覆蓋或插入。
  • 擴容:負載因子 0.75,容量翻倍,重新計算索引((n-1) & hash)。

Q23: hashCode() / equals() 契約?

  1. equals 相等 → hashCode 必相等。
  2. hashCode 相等 → equals 不一定相等(哈希衝突)。
  3. 重寫 equals 必須重寫 hashCode,否則 Map/Set 失效。

Q24: HashMap vs Hashtable?

點HashMapHashtable
Null Key/Value允許不允許
線程安全非安全同步方法(性能差)
迭代器fail-fastEnumerator(非 fail-fast)
推薦單線程/手動同步遺留類,建議用 ConcurrentHashMap

Q25: Array vs ArrayList?

  • Array:固定長度、存基本類型/對象、性能最高。
  • ArrayList:動態擴容、僅存對象(自動裝箱)、功能豐富。
  • 基本類型固定長度場景用 Array 避免裝箱開銷。

Q26: ArrayList vs LinkedList?

操作ArrayListLinkedList
隨機訪問O(1) ✅O(n)
頭尾增刪O(n) 擴容/移位O(1) ✅
中間增刪O(n) 移位O(n) 查找 + O(1) 插入
內存緊湊額外 prev/next 指針

Q27: Comparable vs Comparator?

  • Comparable:內部比較,compareTo(this, other),自然順序。
  • Comparator:外部比較,compare(o1, o2),策略模式,可多種排序。

Q28: PriorityQueue 原理?

基於最小堆(默認自然順序或 Comparator),無界、非線程安全、offer/poll 為 O(log n)。

Q29: Big-O 符號與集合選型?

描述最壞情況時間/空間複雜度。選集合時:查找多用 HashMap/HashSet O(1);頻繁頭尾增刪用 LinkedList;隨機訪問用 ArrayList;有序需求用 TreeMap/TreeSet O(log n)。

Q30: 有序 vs 無序數組權衡?

  • 有序:查找 O(log n),插入 O(n) 需移位。
  • 無序:查找 O(n),插入 O(1) 尾部追加。

Q31: 集合最佳實踐?

  1. 預估大小指定初始容量(new ArrayList(100))。
  2. 全程使用泛型,編譯期類型安全。
  3. 優先用 JDK 不變類(String、Integer)作 Map Key,免寫 hashCode/equals。
  4. 面向接口編程:List<String> list = new ArrayList<>()。
  5. 空集合返回 Collections.emptyList(),勿返回 null。

Q32: Enumeration vs Iterator?

  • Enumeration:舊 API,2倍速、少內存,但不安全、無刪除。
  • Iterator:安全、支持刪除、fail-fast、通用。

Q33: HashSet vs TreeSet?

實現HashSetTreeSet
底層HashMapTreeMap (紅黑樹)
順序無序有序 (自然/Comparator)
增刪查O(1)O(log n)

第五部分:垃圾收集器(GC)

Q34: GC 目的與觸發時機?

  • 目的:識別並回收不可達對象,釋放內存。
  • 觸發:Eden 區滿、老年代滿、元空間滿、System.gc() 提示、JVM 判斷必要時。

Q35: System.gc() / Runtime.gc() 作用?

只是建議 JVM 執行 GC,不保證立即執行,由 JVM 決策。

Q36: finalize() 何時調用?作用?

  • 對象被 GC 前調用(僅一次)。
  • 用於釋放非堆資源(文件句柄、Socket、JNI 內存)。不推薦依賴,不可預測、影響性能,用 try-with-resources / Cleaner (JDK9+) 替代。

Q37: 引用置 null 後內存立即釋放嗎?

不會。下一次 GC 週期中該對象成為可回收候選者。

Q38: JVM 堆結構與永久代?

  • 堆 = 年輕代 + 老年代。
  • 年輕代 = Eden + S0 + S1。
  • 永久代:存類元數據、常量池、靜態變量(JDK 7)。JDK 8 移除,改為元空間,使用本地內存。

Q39: Serial vs Throughput 收集器?

  • Serial:單線程、Client 模式默認、小應用(~100MB 堆)。
  • Throughput (Parallel):多線程並行新生代、Server 模式默認、中大型應用、追求高吞吐量。

Q40: 對象何時可被回收?

不可達性分析:從 GC Roots 搜索無引用鏈可達 → 可回收。

Q41: 永久代/元空間會 GC 嗎?

會。類卸載、常量清理發生在 Full GC 中。元空間滿觸發 Full GC,故需合理配置 -XX:MaxMetaspaceSize。


(下篇預告:異常處理、I/O、JDBC、反射、JVM 調優、Spring、MyBatis、分布式、微服務、設計模式、演算法)

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved