Java基礎-代碼執行順序(重要)


Java代碼初始化順序
java

    1.由 static 關鍵字修飾的(如:類變量(靜態變量)、靜態代碼塊)將在類被初始化建立實例對象以前被初始化,並且是按順序從上到下依次被執行。靜態(類變量、靜態代碼塊)屬於類自己,不依賴於類的實例。ide

    2.沒有 static 關鍵字修飾的(如:實例變量(非靜態變量)、非靜態代碼塊初始化其實是會被提取到類的構造器中被執行的,可是會比類構造器中的代碼塊優先執行到,非靜態(實例變量、非靜態代碼塊)的地位是相等的,它們將按順序被執行。
函數


形參:this

  1. 好比你定義一個函數void add(int a, int b),這裏的a和b就是形參。spa

  2. 當你進行函數調用的時候,add(1, 2),這裏的1和2就是實參。.net


向前引用:對象

所謂向前引用,就是在定義類、接口、方法、變量以前使用它們。接口


成員變量:
    在類體裏面定義的變量稱爲成員變量;
    若是該成員變量有 static 關鍵字修飾,則該成員變量稱爲 靜態變量類變量
    若是該成員變量沒有 static 關鍵字修飾,則該成員變量被稱爲 非靜態變量實例變量

局部變量:
    形參、方法內定義的變量、代碼塊中定義的變量,都屬於局部變量。

類變量 (靜態變量
    1. 能夠向前引用
    2. 變量屬於類自己
    3. 類變量不依賴類的實例,類變量只在初始化時候在方法區中被分配一次空間,不管類的實例被建立幾回,都再也不爲類變量分配空間
    4. 經過類的任意一個實例來訪問類變量,底層都將將其轉爲經過類自己來訪問類變量,它們的效果是同樣的
    5. 一旦類變量的值被改變,經過類或類的任意一個實例來訪問類變量,獲得的都將是被改變後的值
    6. 將在類的初始化以前初始化

實例變量(非靜態變量)
    1. 不能向前引用,若是向前引用,則稱爲非法向前引用,這是不容許的
    2. 變量屬於類的實例對象
    3. 隨着類的實例被建立而分配內存空間

非靜態代碼塊
    直接由 { } 包起來的代碼,稱爲非靜態代碼塊

靜態代碼塊
    直接由 static { } 包起來的代碼,稱爲靜態代碼塊

類變量(靜態變量)、實例變量(非靜態變量)、靜態代碼塊、非靜態代碼塊的初始化時機
    由 static 關鍵字修飾的(如:類變量[靜態變量]、靜態代碼塊)將在類被初始化建立實例對象以前被初始化,並且是按順序從上到下依次被執行;
    沒有 static 關鍵字修飾的(如:實例變量[非靜態變量]、非靜態代碼塊)初始化其實是會被提取到類的構造器中被執行的,可是會比類構造器中的 代碼塊優先執行到,其也是按順序從上到下依次被執行。內存


示例代碼:ci

public class Statical {
 /**
  * 靜態代碼塊 類變量(靜態變量)能夠向前引用(即:先引用,再定義)
  */
 static {
  name = "fancydeepin"; // name 的定義在使用以後
  System.out.println("--->  靜態代碼塊被執行   <---");
 }
 /**
  * 類變量(靜態變量)在類的初始化以前初始化,不管類的實例將被建立多少個 凡 static修飾的,都將按位置被順序執行,因此, name
  * 的值最終輸出 fancy 而不是上面的 fancydeepin
  */
 public static String name = "fancy"; // 類變量(靜態變量)
 private String mail = "myEmail"; // 實例變量(非靜態變量),定義時指定初始值,會比在構造器賦予值更早執行
 public Statical() {
  mail = "fancydeepin@yeah.net";
  System.out.println("---> 構造器代碼塊被執行 <---");
 }
 /**
  * 非靜態代碼塊 實際上,非靜態代碼塊在類初始化建立實例時,將會被提取到類的構造器中, 可是,非靜態代碼塊會比構造器中的代碼塊優先被執行
  * 因此,mail 最終輸出的是類構造器中給定的值,也就是 fancydeepin@yeah.net 而不是
  * 1525336367@qq.com,更不是 myEmail
  */
 {
  mail = "1525336367@qq.com";
  System.out.println("---> 非靜態代碼塊被執行 <---");
 }
 public static void main(String[] args) {
  Statical statical = new Statical();
  System.out.println(name);
  System.out.println(statical.mail);
 }
}


輸出結果:

--->  靜態代碼塊被執行   <---
---> 非靜態代碼塊被執行 <---
---> 構造器代碼塊被執行 <---
fancy
fancydeepin@yeah.net


容易混淆的一個知識點

    靜態方法只容許直接訪問靜態成員,而實例方法中能夠訪問靜態成員和實例成員,緣由是類尚未實例化,所實例成員也沒有被建立,靜態方法中所以也不能用this。


錯誤:
class A{
private int a;
static void f()
{
a=1;
}
}

正確:
private static int a;
static void f()
{
a=1;
}
}

固然靜態方法能夠經過對象間接訪問非靜態成員的

public static void main(String[] args) {
  Statical statical = new Statical();
  System.out.println(name);
  System.out.println(statical.mail);
  }

    在靜態方法main中name是靜態變量能夠直接訪問,而mail屬於非靜態態變量,System.out.println(mail)直接訪問會報錯,必須經過實例對象statical間接訪問。

相關文章
相關標籤/搜索