Java的類的載入機制
1、編譯和執行概念要搞清:編譯即javac的過程,負責將.java檔案compile成.class檔案,主要是型別、格式檢查與編譯成位元組碼檔案,而載入是指java
*的過程,將.class檔案載入到記憶體中去解釋執行,即執行的時候才會有載入一說。
2、類的載入時機,肯定是在執行時,但並不是一次性全部載入,而是按需動態,依靠反射來實現動態載入,一般來說一個class只會被載入一次,之後就會從jvm的class例項的快取中獲取,誰用誰取就可以了,不會再去檔案系統中載入.class檔案了。
一個類在如下情況下才會被載入:
- 當遇到
new
位元組碼被執行時。例如,SomeClass f = new SomeClass();
- 當靜態引用一個類時或類中變數。例如,
System.out
;
-----------------------------------------------------------------------------------------------------------------------------------------------------
為什麼介面中的常量必須使用public static final修飾
public: 使介面的實現類可以使用這個常量
static:static修飾就表示它屬於類的,隨的類的載入而存在的,如果是非static的話,
就表示屬於物件的,只有建立物件時才有它,而介面是不能建立物件的,所以
介面的常量必須定義為static
-----------------------------------------------------------------------------------------------------------------------------------------------------
java程式在執行過程中,類,物件以及它們成員載入、初始化的順序如下: 1、首先載入要建立物件的類及其直接與間接父類。 2、在類被載入的"同時"會將靜態成員進行載入,主要包括靜態成員變數的初始化,靜態語句塊的執行,在載入時按程式碼的先後順序進行。 3、需要的類載入完成後,開始建立物件,首先會載入非靜態的成員,主要包括非靜態成員變數的初始化,非靜態語句塊的執行,在載入時按程式碼的先後順序進行。Private final int int1=rd1.nestInt(10); //生成隨機數並賦值給常量int1
Private static final int int2=rd1.nestInt(10); //生成隨機數並賦值給常量int2 那麼以上兩條語句有什麼差別嗎?我們首先來看Private final int int1=rd1.nestInt(10)這條語句。雖然int1也是一個常量,但是其是在物件建立的時候初始化的。如現在需要建立兩個物件,那麼需要對這個變數初始化兩次。而在兩次物件初始化的過程中,由於生成的隨機數不同,所以常量初始化的值也不同。最後導致的結果就是,雖然int1是常量,但是在不同物件中,其值有可能是不同的。可見,使用final的Java常量定義並不是恆定不變的。因為預設情況下,定義的常量是在物件建立的時候被初始化。如果在建立常量時,直接賦一個固定的值,而不是通過其他物件或者函式來賦值,那麼這個常量的值就是恆定不變的,即在多個物件中值也使相同的。但是如果在給常量賦值的時候,採用的是一些函式或者物件(如生成隨機數的Random物件),那麼每次建立物件時其給常量的初始化值就有可能不同。這往往是程式開發人員不原意看到的。有時候程式開發人員希望建立再多的物件,其在多個物件中引用常量的值都是相同的。 為了確保在所有情況下(即建立多個物件情況下)應用程式還能夠得到一個相同值的常量,那麼就最好告訴編譯器,在程式碼裝載的時候就初始化常量的值。然後在後續建立物件的時候,只引用這個常量物件的地址,而不對其再進行再次初始化。就如同Private static final int int2=rd1.nestInt(10)這種形式來定義常量。如此,在後續多次建立物件後,這個常量int2的值都是相同的。因為在建立物件時,其只是引用這個常量,而不會對這個常量再次進行初始化。
所以,總結一下:
1、如果常量引用的是一個固定值,那麼加不加static的效果是一樣的,除非宣告為public的公共常量,需要加上static,可以直接呼叫。
2、如果常量引用的是一個函式,或者其他物件的賦值,那麼就必須加上static了,要不,你就為莫名其妙的錯誤而頭大了