Java 程式設計師面試寶典:50 道高價值核心題目全解析
針對準備入職的 Java 開發者,本文精選 50 道高頻面試題,涵蓋基礎語法、集合框架、並發編程、JVM 記憶體、Spring 生態、資料庫、設計模式等核心領域。每題附帶標準答案與深度解析,參考最新 JDK 版本,剔除過時內容(如 EJB 2.x),補充演算法、架構設計等實戰考點。
第一部分:Java 基礎核心(第 1-15 題)
1. 面向對象四大特性
答案:封裝、繼承、多態、抽象。
- 封裝:隱藏內部實現,暴露公共介面(如洗衣機面板)
- 繼承:子類復用父類邏輯,實現擴展與多態基礎
- 多態:編譯時多態(重載)vs 運行時多態(重寫),核心是「同一介面,不同實現」
- 抽象:提取共性建立模型,關注「是什麼」而非「怎麼做」
2. 訪問修飾符權限表
| 修飾符 | 同類 | 同包 | 子類 | 其他包 |
| public | ✓ | ✓ | ✓ | ✓ |
| protected | ✓ | ✓ | ✓ | ✗ |
| default | ✓ | ✓ | ✗ | ✗ |
| private | ✓ | ✗ | ✗ | ✗ |
3. String 是基本類型嗎?
不是。Java 僅有 8 種基本類型:byte, short, int, long, float, double, char, boolean。String 是引用類型,屬於 java.lang 套件。
4. float f = 3.4; 編譯錯誤原因
3.4 是 double 字面值,賦值給 float 屬於窄化轉型,會丟失精度。正確寫法:float f = 3.4F; 或 float f = (float) 3.4;。
5. short s1 = 1; s1 = s1 + 1 vs s1 += 1
s1 = s1 + 1:1 為 int,運算結果為 int,需強轉
s1 += 1:隱含強轉,等價於 s1 = (short)(s1 + 1),編譯通過
6. Java 有 goto 嗎?
goto 是保留字,不可使用。同樣保留字還有 const。
7. int vs Integer 深度解析
- 基本差異:
int 基本類型,Integer 包裝類
- 自動裝箱/拆箱:JDK 1.5+ 編譯器自動轉換
- 緩存機制:
Integer.valueOf() 緩存 [-128, 127] 範圍對象
Integer f1 = 100, f2 = 100; // 緩存區間,同一對象
Integer f3 = 150, f4 = 150; // 超出緩存,新建對象
System.out.println(f1 == f2); // true
System.out.println(f3 == f4); // false
面試陷阱:== 比較引用,equals() 比較值。緩存範圍可通過 -XX:AutoBoxCacheMax 調整。
8. & vs &&、| vs ||
&&、||:短路運算,左邊決定結果時右邊不執行
&、|:邏輯運算,兩邊皆執行
實戰案例:username != null && !username.equals("") 順序不可換,否則空指針異常。
9. 記憶體區域:棧、堆、方法區
- 棧:基本類型變量、對象引用、方法幀、執行上下文(快、小、線程私有)
- 堆:
new 出來的對象實例、陣列(大、GC 主戰場、線程共享)
- 方法區:類資訊、常量、靜態變量、JIT 編譯代碼(JDK 8 後為 Metaspace)
String str = new String("hello");
// str 變量在棧
// new String() 對象在堆
// "hello" 字面量在方法區(常量池)
補充:逃逸分析可將未逃逸對象標量替換至棧上分配。
10. Math.round(-11.5) = -11 原理
四捨五入實為 加 0.5 後向下取整:Math.floor(x + 0.5)。負數 -11.5 + 0.5 = -11.0,floor 為 -11。
11. switch 支援類型演進
- JDK 1.4-:
byte, short, char, int
- JDK 1.5+:
enum
- JDK 1.7+:
String
- 不支援:
long, float, double, boolean
12. 高效計算 2 * 8
2 << 3(左移 3 位 = 乘 2³)。hashCode 中 31 * num 優化為 (num << 5) - num。
13. 陣列 length vs String length()
- 陣列:
length 屬性
- String:
length() 方法
- 集合:
size() 方法
14. 跳出多層迴圈
outer: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (condition) break outer; // 標籤 break
}
}
建議:盡量避免,改用方法返回或標誌位,提升可讀性。
15. 建構子能否被重寫?
不能。建構子不被繼承,只能重載。子類透過 super() 呼叫父類建構子。
第二部分:核心進階(第 16-30 題)
16. equals 與 hashCode 契約
equals(true) → hashCode() 必相等
hashCode() 相等 → equals() 不一定相等
- 違反契約導致
HashSet、HashMap 異常(重複元素、查找失效)
高質量 equals 實現清單:== 檢查、instanceof、關鍵屬性比較、滿足自反/對稱/傳遞/一致性、重寫 equals 必重寫 hashCode。
17. String 能否被繼承?
不能。final 類。複用請用組合(HAS-A)而非繼承(IS-A)。
18. Java 參數傳遞:值傳遞還是引用傳遞?
值傳遞。傳遞對象時,傳的是引用的副本。可修改對象內部狀態,但無法改變引用本身指向。
19. String / StringBuilder / StringBuffer
| 類別 | 可變性 | 線程安全 | 效能 | 適用場景 |
| String | 不可變 | - | 低(拼接產生新對象) | 常量、少量拼接 |
| StringBuffer | 可變 | 同步(synchronized) | 中 | 多線程頻繁修改 |
| StringBuilder | 可變 | 非同步 | 高(JDK 1.5+) | 單線程頻繁修改 |
面試題:String a = "Programming"; String c = "Program" + "ming"; a == c → true(編譯期常量折疊)。
20. 重載 vs 重寫
| 特性 | 重載 | 重寫 |
| 發生位置 | 同一類 | 父子類 |
| 參數列表 | 必須不同 | 必須相同 |
| 返回類型 | 可不同 | 相同/协变 |
| 異常 | 無限制 | 子類異常⊆父類 |
| 多態類型 | 編譯時(靜態) | 運行時(動態) |
為何不能按返回類型重載?:JVM 方法簽名不含返回類型,調用時無法區分。
21. JVM 類加載機制(雙親委派模型)
- 加載:讀取 .class → 字節數組 → 生成
Class 對象
- 鏈接:驗證 → 準備(靜態變量賦默認值) → 解析(符號引用→直接引用)
- 初始化:執行
<clinit>()(靜態塊、靜態變量賦值),先初始化父類
類加載器層級:Bootstrap(rt.jar)→ Extension(ext 目錄)→ Application(classpath)→ Custom。雙親委派保護核心類庫不被篡改。
22. char 能存中文嗎?
能。Java 內部用 Unicode(2 字節/16 bit),一個 char 存一個 Unicode 碼點。注意:補充字符需 2 個 char(代理對)。
23. 抽象類 vs 介面
| 特性 | 抽象類 | 介面 |
| 實例化 | 不可 | 不可 |
| 建構子 | 可有 | 不可 |
| 方法 | 抽象+具體 | JDK 8 前全抽象,8+ 可 default/static |
| 成員變量 | 任意修飾符 | 隱含 public static final |
| 繼承/實現 | 單繼承 | 多實現 |
24. 靜態內部類 vs 非靜態內部類
- 靜態內部類:無需外部類實例即可創建,無外部類引用
- 非靜態內部類:隱含持有外部類引用,需
outer.new Inner() 創建
記憶體洩漏隱患:非靜態內部類實例長期存活會阻礙外部類回收,Handler、AsyncTask 常見問題。
25. Java 會有記憶體洩漏嗎?
會。GC 只回收不可達對象。無用但可達對象(如集合中過期引用、未關閉資源、靜態集合累積)導致洩漏。
// 經典棧洩漏案例
public Object pop() {
Object o = elements[--size];
elements[size] = null; // 必須手動清除引用!
return o;
}
26. abstract 方法限制
- 不能 static:靜態方法屬於類,不可重寫
- 不能 native:native 有實現,abstract 無實現
- 不能 synchronized:同步屬於實現細節
27. 靜態變量 vs 實例變量
- 靜態變量:屬於類,
static 修飾,類加載時初始化,單一拷貝共享
- 實例變量:屬於對象,對象創建時初始化,每個對象一份
28. 靜態方法能調用非靜態方法嗎?
不能。非靜態方法需對象實例,靜態方法執行時對象可能未創建。
29. 對象克隆兩種方式
- Cloneable + clone():淺克隆,需手動處理深克隆
- Serializable 序列化/反序列化:真正深克隆,編譯期檢查可序列化,推薦
// 深克隆工具類
public static T clone(T obj) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bout);
oos.writeObject(obj);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bin);
return (T) ois.readObject();
}
30. GC 核心原理與參數
- 分代收集:新生代(Eden + Survivor)→ 老年代
- Minor GC:新生代,頻繁、快
- Major/Full GC:老年代,較慢、Stop-The-World
關鍵參數:-Xms/Xmx 堆大小、-Xmn 新生代、-XX:+PrintGCDetails、-XX:+UseG1GC 等。
第三部分:異常、集合、並發、新特性(第 31-50 題)
31. String s = new String("xyz") 創建幾個對象?
兩個:常量池 "xyz" + 堆上 new 出的對象。
32. 介面繼承介面、抽象類實現介面、抽象類繼承具體類
皆可行。抽象類繼承具體類需父類有明確建構子。
33. 一個 .java 檔可含多個類嗎?
可,但僅一個 public 類,且檔名必須與 public 類同名。
34. 匿名內部類
可繼承類/實現介面,常用於事件監聽、回調。
35. 內部類訪問外部類成員
可訪問外部類所有成員(含 private)。
36. final 關鍵字三大用法
- 修飾類:不可繼承
- 修飾方法:不可重寫
- 修飾變量:只能賦值一次(引用不變,對象內容可變)
37. 靜態塊/建構子執行順序
// 輸出:1a2b2b
// 順序:父類靜態 → 子類靜態 → 父類非靜態/建構子 → 子類非靜態/建構子
38. 基本類型 ↔ 字串轉換
- 字串→基本:
Integer.parseInt()、Double.valueOf()
- 基本→字串:
String.valueOf()、"" + num
39. 字串反轉(遞歸實現)
public static String reverse(String s) {
if (s == null || s.length() <= 1) return s;
return reverse(s.substring(1)) + s.charAt(0);
}
40. 編碼轉換:GB2312 → ISO-8859-1
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");
41-42. 日期時間處理
- 獲取時間:
Calendar.getInstance().get()
- 時間戳:
System.currentTimeMillis()
- 月末日:
cal.getActualMaximum(Calendar.DAY_OF_MONTH)
- 格式化:
SimpleDateFormat.format(date)
- 昨天:
cal.add(Calendar.DATE, -1)
43. Java vs JavaScript
完全不同語言。Java:靜態、編譯、強類型、面向對象。JS:動態、解釋、弱類型、基於原型、函數優先。核心差異在類型系統與執行模型。
44. assert 斷言用法
- 開發/測試開啟(
-ea),生產關閉(-da)
- 檢查前置/後置條件、不變式
- 不可改變程序狀態、不可用於 public 方法參數驗證
45. Error vs Exception
- Error:系統級、不可恢復(OOM、StackOverflow)
- Exception:程序級、可捕獲處理(受檢/非受檢)
46. try-return-finally 執行順序
finally 必執行,在 return 返回調用者之前執行。finally 中修改返回值會覆蓋 try 的返回值(不推薦)。
47. 異常處理五關鍵字
try { ... }
catch (ExceptionType e) { ... }
finally { ... }
throw new MyException();
throws ExceptionType1, ExceptionType2
48. 受檢異常 vs 非受檢異常
- 受檢:編譯期強制處理(IOException)、可恢復情況
- 非受檢:RuntimeException 子類、編程錯誤(NPE、越界)
- 原則:可恢復用受檢、編程錯誤用非受檢、優先用標準異常
49. 常見運行時異常
NullPointerException、IndexOutOfBoundsException、IllegalArgumentException、ClassCastException、ArithmeticException、SecurityException
50. final / finally / finalize
| 關鍵字 | 類型 | 作用 |
| final | 修飾符 | 不可變/不可繼承/不可重寫 |
| finally | 代碼塊 | 異常處理最後執行、資源釋放 |
| finalize | Object 方法 | GC 前調用(不可靠、Java 9 棄用) |
面試加分建議
- 原理優於背誦:說出
hashCode 為何用 31、為何 String 不可變、JVM 記憶體模型
- 實戰經驗:結合項目講解 GC 調優、並發問題排查、性能優化案例
- 源碼閱讀:熟悉 HashMap、ArrayList、ThreadPoolExecutor、Spring 核心源碼
- 新特性跟進:JDK 8-21 Stream、Optional、Record、Pattern Matching、Virtual Threads
- 系統設計:大型網站架構、分散式一致性、快取策略、資料庫優化
這 50 道題覆蓋 Java 核心知識體系 90% 以上高頻考點。建議分模塊專項攻克,每題做到「能講清原理、能寫出正確代碼、能分析優缺點、能聯繫實戰場景」,面試成功率將大幅提升。
- 上一篇文章: Java 四大引用類型深度解析:強、軟、弱、虛擬引用
- 下一篇文章: MyBatis 多參數傳遞三種方案詳解與最佳實踐
Copyright ©
程式碼之家 All Rights Reserved