一道面試題:靜態代碼塊的執行順序


先來看一道最常見的面試題:靜態代碼塊的執行順序?

看一下實際運行:

class A{
    static {
        System.out.println("A的靜態代碼塊");
    }
        {
        System.out.println("A的構造代碼塊/非靜態代碼塊");
    }
    public A() {
        System.out.println("A的構造函數");
    }
}
class B extends A{
     static {
            System.out.println("B的靜態代碼塊");
        }
            {
            System.out.println("B的構造代碼塊/非靜態代碼塊");
        }
        public B() {
            System.out.println("B的構造函數");
        }    
}
//測試程序執行
public
static void main(String[] args) { System.out.println("==== main開始執行 ===="); new B(); System.out.println("==== B已經被創建 ====="); }

答案是:

==== main開始執行 ====
A的靜態代碼塊
B的靜態代碼塊
A的構造代碼塊/非靜態代碼塊
A的構造函數
B的構造代碼塊/非靜態代碼塊
B的構造函數
==== B已經被創建 =====

好了,現在開始小白的問答環節:

 

Q1:不是說,靜態塊里的內容在類被加載的時候就執行,存在方法區(靜態區)中,那為什么是先有main開始執行的語句打印呢?

A1:首先要明白,什么叫類加載:類加載就是把需要的類的代碼加載到內存中,且在此類首次使用時靜態代碼塊被加載執行,也就是說靜態代碼塊只執行一次

什么時候有類加載:1.創建實例   2.調用該類的靜態方法時(靜態塊代碼優先於靜態函數執行) 3.使用該類的非常量靜態字段 4.使用反射方法時  5.初始化該類的子類

 

Q2:上面說存在方法區中,那么方法區是什么?Java內存布局里沒有方法區呀?

A2:《Java虛擬機規范》只是規定了有方法區這個概念,在HotSpot上使用永久代來實現方法區。而到了JDK8,永久代被元空間(MetaSpace)替換,其他內容由永久代移入元空間,比如說

類元信息,字段,靜態屬性,方法,常量等,除了字符串常量,它被移入了堆內存

 

Q3:什么是構造代碼塊呢?

A3:構造代碼塊:初始化所有對象。屬於對象的,在new 的時候才會執行,而構造函數是new的時候,調用了構造方法,所以構造代碼塊會先一步

 

Q4:為什么我構造方法寫成了 public void A(){} 就不可以了呢?構造方法為什么不可以有返回值?

A4:構造方法在Java語言規范里面叫 “Constructor” ,並不是一個成員方法(成員方法叫 Method),其實應該叫 “構造器”更合適。

   構造方法在類創建的期間(new)被執行用於對象初始化的,只有在構造方法執行完了,類的創建才算是完成了。

  既然是用於初始化對象的,那么沒有返回值是很正常的事情了,虛擬機規范中也是這么形容的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM