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

【Java 每日一題】20170301:類初始化順序與靜態/實例變數賦值陷阱

     編輯:Java 相關知識

本題考察 Java 類初始化過程中靜態變數、實例變數、建構子、實例初始化塊的執行順序,以及前向引用導致的讀取預設值陷阱。理解初始化時間線是解題關鍵。

題目程式碼

package Mar2017;
public class Ques0301 {
    private int a = getB();  // 實例變數初始化表達式
    private int b = 1;       // 實例變數初始化
    private int getB() { return b; }

    public static void main(String[] args) {
        System.out.println((new Ques0301()).a);
    }
}

初始化執行順序時間線

  1. 靜態變數/靜態初始化塊:類載入時,按原始碼順序執行(本題無靜態成員)
  2. 實例變數初始化 / 實例初始化塊:按原始碼順序執行,在建構子之前
  3. 建構子主體:最後執行

逐步執行分析

new Ques0301() 執行流程:

1. 分配記憶體,所有欄位設為預設值:a=0, b=0
2. 執行實例初始化(按宣告順序):
   a. 第 1 行:a = getB()  → 調用 getB()
      - getB() 返回 b
      - 此時 b 尚未執行初始化表達式,仍為預設值 0
      - 所以 a = 0
   b. 第 2 行:b = 1  → b 變為 1(但 a 已固定為 0)
3. 執行建構子主體(隱式無參建構子,無額外代碼)
4. 物件建立完成,main 印出 a = 0

關鍵知識點

  1. 實例變數初始化順序 = 宣告順序,早於建構子
  2. 前向引用:在初始化表達式中調用方法,該方法讀取尚未初始化的欄位 → 讀到預設值
  3. 編譯器不禁止:合法但極易產生邏輯 Bug
  4. 靜態成員同理:靜態初始化塊/變數也按宣告順序,前向引用讀到預設值

答案

輸出結果:0

修正建議

// 方案 1:調整宣告順序
private int b = 1;
private int a = getB();  // 現在 getB() 讀到 b=1

// 方案 2:在建構子中初始化
private int a; private int b;
public Ques0301() { b = 1; a = getB(); }

// 方案 3:getB() 直接返回常數或計算值,不依賴欄位
private int a = 1; // 或 private int a = computeA();

延伸練習

class Test {
    static int x = getY();
    static int y = 2;
    static int getY() { return y; }
    public static void main(String[] args) { System.out.println(x); }
}
// 輸出? 0(同理:靜態初始化按順序,x 初始化時 y 尚為 0)

總結

類初始化順序是 Java 基礎中極易掉坑的考點。鐵律:**靜態→實例(按宣告順序)→建構子**。任何在初始化表達式中調用方法讀取同類欄位,必須確認該欄位已完成初始化,否則讀到預設值導致邏輯錯誤。

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