03_javaSE面試題:類初始化和實例初始化

題目

下面代碼運行的結果是什麼?ide

Father 類code

/**
 * @author kevin
 * @date 2019/7/8 15:48
 */
public class Father {
    private int i = test();
    private static  int j = method();

    static {
        System.out.print("(1)");
    }
    Father(){
        System.out.print("(2)");
    }
    {
        System.out.print("(3)");
    }

    public int test(){
        System.out.print("(4)");
        return 1;
    }
    private static int method() {
        System.out.print("(5)");
        return 1;
    }
}

Son 類對象

/**
 * @author kevin
 * @date 2019/7/8 15:55
 */
public class Son extends Father {
    private int i = test();
    private static int j = method();

    static {
        System.out.print("(6)");
    }
    Son(){
        System.out.print("(7)");
    }
    {
        System.out.print("(8)");
    }


    public  static  int method(){
        System.out.print("(10)");
        return 1;
    }
    @Override
    public int test() {
        System.out.print("(9)");
        return 1;
    }

    public static void main(String[] args) {
        Son s1 = new Son();
        System.out.println();
        Son s2 = new Son();
    }

}

解析

類初始化過程

分析

  • 一個類要建立實例須要先加載並初始化該類
    • main方法所在的類須要先加載和初始化
  • 子類初始化須要先初始化父類
  • 一個類初始化就是執行<clinit>()方法
    • <clinit>()方法由靜態類變量顯示賦值代碼和靜態代碼塊組成
    • 靜態類變量顯示賦值代碼和靜態代碼塊按照順序執行
    • <clinit>()方法只執行一次

對應代碼

  • 子類初始化 -> 父類初始化

1、先執行父類初始化get

  • 父類初始化,執行<clinit>()方法
  • 1.j = method(); --輸出(5)
  • 2.父類的靜態代碼塊;--輸出 (1)

2、再執行子類初始化虛擬機

  • 子類初始化,執行<clinit>()方法
  • 1.j = method(); --輸出 (10)
  • 2.子類的靜態代碼塊 ;--輸出(6)

整個類初始化完成後,輸出it

(5)(1) (10) (6)

類實例化過程

分析

  • 實例初始化過程就是執行<init>() 方法
    • <init>()方法可能重載有多個,有幾個構造器就有幾個<init>()方法
    • <init>() 方法由非靜態實例變量顯示賦值代碼和非靜態代碼塊、對應的構造器組成
    • 非靜態實例變量顯示賦值代碼和非靜態代碼塊順序執行,構造器最後執行
    • 每次建立實例對象,調用構造器就是執行對應的<init>()方法
    • <init>()方法首行是super()或super(參數),即父類的<init>()方法io

      對應代碼

      這裏你們注意一點
      因爲子類重寫了父類的 test()方法,會執行子類的test()方法
      因此整個輸出爲
    (9)(3)(2)(9)(8)(7)

結果

因此整個結果爲class

(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)
(9)(3)(2)(9)(8)(7)

總結

其實,這主要考驗你們對類初始化和實例化的考驗,以及父類子類之間的關係。
我在stackoverflow 找到一個回答,感受很好,簡潔的解釋了初始化和實例化test

  • <init> is the (or one of the) constructor(s) for the instance, and non-static field initialization.變量

  • <clinit> are the static initialization blocks for the class, and static field initialization.

class X {

   static Log log = LogFactory.getLog(); // <clinit>

   private int x = 1;   // <init>

   X(){
      // <init>
   }

   static {
      // <clinit>
   }

}

固然這裏只是簡單分析了一下,若是你們想更深刻了解,你們能夠看看 《深刻JAVA虛擬機第二版.》這本書。 好了玩的開心!

相關文章
相關標籤/搜索