類的初始化變量和方法的執行順序(父子類)


static和沒有static的區別
*static的屬性/方法在類加載時就已經做好准備,因此類名.就可以調用,與對象存在不存在無關。
*非static的屬性/方法隸屬於對象,必須先創建對象,才能使用。
  static的方法中,不能使用非靜態的屬性或者方法,必須先創建對象,然后用對象.調用;而非static的方法中,可以直接使用靜態的屬性或方法。
只有隸屬於類(所有對象共享)的屬性才能加static,static不能隨便加。

代碼塊 -- java允許直接用{}寫代碼,叫代碼塊。
*寫在類體中的代碼塊叫構造塊,每創建一個對象,構造塊都會被執行一次。
*前面加static的構造塊叫靜態代碼塊,類加載時執行一次。

對象創建的過程
 a.單個對象創建的執行過程
(1)main()方法是程序的入口,使用new關鍵字創建對象時會在堆區申請內存空間;
(2)若成員變量沒有指定初始值,則采用默認初始化方式處理;
(3)若成員變量進行顯式初始化,則采用指定的初始值進行處理;
(4)執行構造塊中的代碼,可以對成員變量進行賦值操作;
(5)執行構造方法體中的代碼,可以對成員變量進行再次賦值;
(6)此時對象創建完畢,繼續向下執行;

b.子類對象創建的執行過程
(1)main()方法是程序的入口,使用new關鍵字創建對象時會在堆區申請內存空間;
(2)先加載父類再加載子類,因此先執行父類的靜態代碼塊再執行子類的靜態代碼塊;
(3)執行父類的構造塊和父類的構造方法體,此時內部的父類對象構造完畢;
(4)執行子類的構造塊和子類的構造方法體,此時子類對象構造完畢;
(5)構造完畢后繼續向下執行;

執行順序:(靜態代碼塊和靜態變量誰在前面就先執行誰)

父類靜態代變量、
父類靜態代碼塊、
子類靜態變量、
子類靜態代碼塊、
父類非靜態變量(父類實例成員變量)、
父類構造函數、
子類非靜態變量(子類實例成員變量)、
子類構造函數。

 

代碼示例

package com.jdk.learn;

public class ClassLoaderTest {

  public static void main(String[] args) {
    son sons=new son();
  }
}

class parent{
  private static int a=1;
  private static int b;
  private int c=initc();
  static {
    b=1;
    System.out.println("1.父類靜態代碼塊:賦值b成功");
    System.out.println("1.父類靜態代碼塊:a的值"+a);
  }
  int initc(){
    System.out.println("3.父類成員變量賦值:---> c的值"+c);
    this.c=12;
    System.out.println("3.父類成員變量賦值:---> c的值"+c);
    return c;
  }
  public parent(){
    System.out.println("4.父類構造方式開始執行---> a:"+a+",b:"+b);
    System.out.println("4.父類構造方式開始執行---> c:"+c);
   }
}

class son extends parent{
  private static int sa=1;
  private static int sb;
  private int sc=initc2();
  static {
    sb=1;
    System.out.println("2.子類靜態代碼塊:賦值sb成功");
    System.out.println("2.子類靜態代碼塊:sa的值"+sa);
  }
  int initc2(){
    System.out.println("5.子類成員變量賦值--->:sc的值"+sc);
    this.sc=12;
    return sc;
  }
  public son(){
    System.out.println("6.子類構造方式開始執行---> sa:"+sa+",sb:"+sb);
    System.out.println("6.子類構造方式開始執行---> sc:"+sc);
  }
}

 

執行結果:

1.父類靜態代碼塊:賦值b成功
1.父類靜態代碼塊:a的值1
2.子類靜態代碼塊:賦值sb成功
2.子類靜態代碼塊:sa的值1
3.父類成員變量賦值:---> c的值0
3.父類成員變量賦值:---> c的值12
4.父類構造方式開始執行---> a:1,b:1
4.父類構造方式開始執行---> c:12
5.子類成員變量賦值--->:sc的值0
6.子類構造方式開始執行---> sa:1,sb:1
6.子類構造方式開始執行---> sc:12

 

總結:

當我們進行new實例化進行操作的時候,JVM都進行了什么操作呢?
如果你看過深入理解jvm的話,應該會比較清楚,當我們使用new關鍵字進行實例化的時候,會進行如下幾步處理:

加載
此階段加載類的字節碼信息到內存
連接
此階段進行驗證,分配默認值,符號引用轉直接引用
初始化
為成員進行賦值等

使用
對實例進行操作比如sons.toString()

對於我們的實例而言,我們只關注連接和初始化階段即可。
連接階段我們按照類結構(成員變量(先),方法(后)等)的順序(不是書寫順序),先對變量進行賦默認值0,對象的話為null。

初始化的時候,就是對對象進行賦值,比如c執行initc()進行賦值。

 

參考博客:https://blog.csdn.net/u014042066/article/details/77574956


免責聲明!

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



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