static語句塊的執行時間

來源:互聯網
上載者:User

標籤:還原序列化   return   block   參考   pac   strong   https   line   src   


package utfTest;


public class Test01 {
public static void main(String[] args) {
//Person.show();
System.out.println("p還沒有初始化");
Class cls=Person.class;
System.out.println("執行了語句:Class cls=Person.class;不知道static語句在這條語句之前是否有輸出");
Person p = new Person();
System.out.println("p剛剛被初始化,這裡輸出是用來驗證static語句塊是在哪裡被輸出的");
p.setName("小明");
p.setAge(18);
Person p1 = p;
p1.setAge(10);
p.setName("小鄒");
System.out.println("p1建立了");
System.out.println(p.getName()+" "+p.getAge());
System.out.println(p1.getName()+" "+p1.getAge());
}
}


class Person{
int age;
String name;
static int id=0;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

static{
System.out.println("這裡輸出的是靜態代碼塊");//這條語句在編譯階段執行,只會被執行一次
System.out.println("id="+id);
}
static public void show(){
System.out.println("這是static方法,我是在什麼時候被輸出的呢?");
}
}

 

運行結果是:

static語句塊是在初始化階段被執行的,而不是類載入階段。

如果在main方法的開頭添加了代碼塊:Person.show();那麼運行結果是:

以下轉載自:46472789

 一、誤區:簡單認為JAVA靜態代碼塊在類被載入時就會自動執行。證錯如下:  

 

  1.  class MyClass1 {
  2.   static {//靜態塊
  3.   System.out.println("static block ");
  4.   }
  5.  }
  6.  public class Main {
  7.   
  8.   Class[] classArray = {
  9.   MyClass1.class//這樣引用該類,必然需要將該類載入到虛擬機器中
  10.   };
  11.   public static void main(String[] args){
  12.   System.out.println("hello word");
  13.   }
  14.   
  15.  }

執行結果:並沒有輸出" static bolck"

二、正解:static塊真正的執行時機。如果瞭解JVM原理,我們知道,一個類的運行分為以下步驟:

 

  1. 裝載
  2. 串連
  3. 初始化

    其中裝載階段又三個基本動作組成:

  1.     通過類型的完全限定名,產生一個代表該類型的位元據流
  2.     解析這個位元據流為方法區內的內部資料結
  3.     構建立一個表示該類型的java.lang.Class類的執行個體

    另外如果一個類裝載器在預先裝載的時遇到缺失或錯誤的class檔案,它需要等到程式首次主動使用該類時才報告錯誤。

 

    串連階段又分為三部分:

  1. 驗證,確認類型符合Java語言的語義,檢查各個類之間的二進位相容性(比如final的類不用擁有子類等),另外還需要進行符號引用的驗證。
  2. 準備,Java虛擬機器為類變數分配記憶體,設定預設初始值。
  3. 解析(可選的) ,在類型的常量池中尋找類,介面,欄位和方法的符號引用,把這些符號引用替換成直接引用的過程。

   

  當一個類被主動使用時,Java虛擬就會對其初始化,如下六種情況為主動使用:

  1. 當建立某個類的新執行個體時(如通過new或者反射,複製,還原序列化等)
  2. 當調用某個類的靜態方法時
  3. 當使用某個類或介面的靜態欄位時
  4. 當調用Java API中的某些反射方法時,比如類Class中的方法,或者java.lang.reflect中的類的方法時
  5. 當初始化某個子類時
  6. 當虛擬機器啟動某個被標明為啟動類的類(即包含main方法的那個類)

    Java編譯器會收集所有的類變數初始化語句和類型的靜態初始化器,將這些放到一個特殊的方法中:clinit。 

 

 
實際上,static塊的執行發生在“初始化”的階段。初始化階段,jvm主要完成對靜態變數的初始化,靜態塊執行等工作。

下面我們看看執行static塊的幾種情況:

1、第一次new A()的過程會列印"";因為這個過程包括了初始化

2、第一次Class.forName("A")的過程會列印"";因為這個過程相當於Class.forName("A",true,this.getClass().getClassLoader());

3、第一次Class.forName("A",false,this.getClass().getClassLoader())的過程則不會列印""。因為false指明了裝載類的過程中,不進行初始化。不初始化則不會執行static塊。

 

 參考資料:《深入Java虛擬機器》

---------------------本文來自 berber78 的CSDN 部落格 ,全文地址請點擊:46472789?utm_source=copy 

static語句塊的執行時間

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.