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

Java 面試必考 4 題深度解析:Integer 快取、字串駐留、final 捕獲、拆箱陷阱

     編輯:Java 相關知識

題目一:Integer == 比較陷阱

Integer a = 1000, b = 1000;
Integer c = 100, d = 100;
System.out.println(a == b); // false
System.out.println(c == d); // true

核心機制:IntegerCache

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

// 預設快取範圍:-128 ~ 127
// 可透過 -XX:AutoBoxCacheMax=2000 擴大上限

解析

  • Integer c = 100 觸發自動裝箱 → Integer.valueOf(100) → 回傳快取物件 → c == d 為 true
  • Integer a = 1000 超出快取範圍 → 每次 new Integer(1000) → 不同物件參考 → false

題目二:字串駐留機制

String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false

記憶體模型

  • 字串常量池:編譯期常量、intern() 結果駐留於此 (JDK 7+ 在 Heap)
  • 堆區:new String() 強制建立新物件
  • s1、s2 指向同一常量池物件;s3 指向堆區新物件

補充:intern() 實戰

String s4 = new String("abc").intern(); // 強制放入/查找常量池
System.out.println(s1 == s4); // true

題目三:匿名內部類捕獲 final 變數

public void startTask(final String name) {
    new Thread(() -> {
        try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
        System.out.println(name); // 編譯器要求 name 為 final 或 effectively final
    }).start();
}

為何需要 final?

  1. 生命週期不匹配:方法結束,區域變數 name 出棧銷毀;但執行緒可能稍後才執行
  2. 值複製機制:final 讓編譯器在匿名類建構子隱式複製一份 name 副本 (val$name) 到實例欄位
  3. 語義保證:effectively final (Java 8+) 表示變數初始化後未重新賦值,編譯器自動視為 final

反編譯視角

class Outer$1 implements Runnable {
    final String val$name; // 複製的副本
    Outer$1(String name) { this.val$name = name; }
    public void run() { System.out.println(this.val$name); }
}

題目四:Integer 與 int 混合比較

Integer a = new Integer(1000);
int b = 1000;
Integer c = new Integer(10);
Integer d = new Integer(10);
System.out.println(a == b); // true
System.out.println(c == d); // false

關鍵規則:== 觸發自動拆箱

  • a == b:Integer 與 int 比較 → a 自動拆箱為 int → 數值比較 → true
  • c == d:兩個 Integer 物件參考比較 → new Integer(10) 建立不同物件 → false (雖 10 在快取範圍,但 new 繞過快取)

最佳實踐

  1. 優先使用基本型別 int,避免不必要的裝箱
  2. 比較包裝類型用 Objects.equals(a, b) 或 a.equals(b) (注意 NPE)
  3. 數值比較明確拆箱:a.intValue() == b
  4. 避免在效能敏感路徑混用包裝/基本型別

總結:建立正確心智模型

場景行為建議
Integer 裝箱-128~127 回傳快取物件依賴快取行為屬實作細節,勿寫依賴此特性的業務邏輯
字串字面值進入常量池,同值共享比較內容用 equals(),== 僅用於檢查同一物件
匿名類捕獲區域變數複製副本,要求 final/effectively finalJava 8+ 可省略 final 關鍵字,但語義不變
包裝類型 == 基本型別觸發自動拆箱明確拆箱或用 Objects.equals,避免隱式行為
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved