Java程序中對類的使用方式分爲兩類 :主動使用和被動使用
主動使用:
- 創建類的實例
- 訪問某個類或接口的靜態變量,或者對該靜態變量賦值
- 調用類的靜態方法
- 反射
- 初始化一個類的子類
- java虛擬機啓動時被標明爲啓動類的類
- 從JDK1.7開始提供的動態語言支持:java.lang.invoke.MethodHandle實例的計息結果REF_getStatic,REF_putStatic,REF_involeStatic句柄對應的類沒有初始化,則初始化
被動使用:
除了以上7中情況,其他適用java類的方法都被看做是對類的被動使用,都不會導致類的初始化。
創建類的實例——創建對象
*注:A是一個擁有屬性的類。
(1)聲明對象時的內存模型
用A a;聲明一個對象a時,將在棧內存爲對象的引用變量a分配內存空間,但A的值爲空,稱a是一個空對象。空對象不能使用,因爲它還沒有引用任何”實體”。
(2)對象實例化時的內存模型
當執行a=new A(3,5);時,會有連接和初始化兩個過程。
連接:連接又分爲驗證、準備、解析三個小步驟。在準備過程中,JVM會在堆內存中爲類的成員變量分配內存,並將其初始化爲各數據類型的默認值;接着進行顯式初始化(類定義時的初始化值),此時,在到達初始化之前,類變量都沒有初始化爲真正的初始值;
解析:解析過程就是在類型的常量池中尋找類、接口、字段和方法的符號引用,把這些符號引用替換成直接引用的過程。
初始化:最後調用構造方法,爲成員變量賦值。返回堆內存中對象的引用(相當於首地址)給引用變量a,以後就可以通過a來引用堆內存中的對象了,此過程爲類變量的真正賦初始值。
(3)創建多個不同的對象實例
一個類通過使用new運算符可以創建多個不同的對象實例,這些對象實例將在堆中被分配不同的內存空間,改變其中一個對象的狀態不會影響其他對象的狀態。例如:
A a1= new A(3,5);
A a2= new A(4,6);
此時,將在堆內存中分別爲兩個對象的成員變量分配內存空間,兩個對象在堆內存中佔據的空間是互不相同的。如果有:
A a1=new A(3,5);
A a2=a1;
則在堆內存中只創建了一個對象實例,在棧內存中創建了兩個對象引用,兩個對象引用同時指向一個對象實例。