標籤:類載入 調用 main AC 類方法 pre font 試題 產生
final:
1.修飾資料
聲明資料為常量,可以是編譯時間常量,也可以是在運行時被初始化後不能被改變的常量。
- 對於基本類型,final使數值不變;
- 對於參考型別,final使引用不變,也就是不能引用其他對象,但是被其引用的對象本身是可以修改的。
final int x = 1;x = 2; // cannot assign value to final variable ‘x‘final A y = new A();y.a = 1;
2.修飾方法
聲明方法不能被子類覆蓋,不能與abstract共存。
註:private方法隱式地被指定為final,如果在子類中定義的方法和基類中的一個 private 方法簽名相同,此時子類的方法不是覆蓋基類方法,而是重載了。
3.修飾類
聲明類不允許被繼承,不能與abstract共存。
static:
1.靜態變數
靜態變數在記憶體中只存在一份,只在類第一次使用時初始化一次。
- 靜態變數:類所有的執行個體都共用靜態變數,可以直接通過類名來訪問;
- 執行個體變數:每建立一個執行個體就會產生一個執行個體變數,它與該執行個體同生共死。
public class A { private int x; // 執行個體變數 public static int y; // 靜態變數 public static void main(String[] args){ System.out.println(A.y); A a = new A(); System.out.println(a.x); }}
2.靜態方法
靜態方法在類的載入時候就存在了,它不依賴於任何執行個體,所以 static 方法必須實現,也就是說它不能是抽象方法(abstract)。
靜態方法可以調用靜態變數,不可調用類的執行個體變數,因為靜態方法隨著類的載入就出現了,而執行個體變數依賴於具體執行個體。
public static void run(){ System.out.println("hello");}
3.靜態代碼塊
靜態代碼塊隨著類載入而載入有多個靜態代碼塊的,按代碼塊前後順序載入一個代碼塊,只執行一次。
static{ System.out.println("hehe");}
4.初始化順序
待用資料>>普通代碼塊、執行個體變數>>建構函式
ps:靜態變數和靜態語句塊哪個先運行取決於它們在代碼中的順序。
存在繼承的情況下,初始化順序:
- 父類(靜態變數、靜態語句塊塊)
- 子類(靜態變數、靜態語句塊)
- 父類(執行個體變數、普通語句塊)
- 父類(建構函式)
- 子類(執行個體變數、普通語句塊)
- 子類(建構函式)
筆試題:下面代碼的輸出為?(關於靜態變數的初始化和賦值)
public class SingleTon { private static SingleTon singleTon = new SingleTon(); public static int count1; public static int count2 = 0; private SingleTon(){ count1++; count2++; } public static SingleTon getSingleTon(){ return singleTon; } public static void main(String[] args) { SingleTon singleTon = SingleTon.getSingleTon(); System.out.println(singleTon.count1); System.out.println(singleTon.count2); }}
答案是:1 0
解析:1.SingleTon singleTon = SingleTon.getSingleTon(); 調用了類方法,觸發類的初始化;
2.類載入時,JVM為類的靜態變數分配記憶體並賦預設值:singleTon = null; count1 = 0; count2 = 0;
3.類初始化,JVM為靜態變數賦值以及執行靜態代碼塊,當給singleTon賦值new SingleTon()時觸發類構造器,調用類的構造方法後count1 = 1,count2 = 1;
4.JVM繼續給count1和count2賦值,count1無賦值操作, count2 = 0;
總結:靜態變數的聲明和賦值是分開的
Java基礎--關鍵字final、static