1. 程式人生 > >java類例項化記憶體過程與面向物件特徵

java類例項化記憶體過程與面向物件特徵

在談到類例項化的記憶體過程時先說說幾個概念:

物件:記憶體上來說是分配在堆上面的一塊記憶體區域
類:把一類具體事物相同特徵,功能/行為抽象為屬性與方法過程。
類是物件的模板,物件是類的具體表現。
建構函式:與類名同名的函式,用來例項化物件並初始化成員變數。
注意:構造器、建構函式不能稱為構造方法。

類的結構:
靜態塊:當對應的class檔案被首次載入到虛擬機器時執行。
程式碼塊
建構函式
靜態屬性與變數首先載入。其次時靜態塊,之後是程式碼塊,最後是建構函式。

具體過程:
當一個類被建立(A a=new A();),並且這個類是首次被載入時,方法區會開闢出一塊記憶體存放類的class檔案並且將全部成員放入。之後會在堆中開闢一塊記憶體,儲存這個類並且將這個類的非靜態的成員變數拷貝過來(靜態成員不拷貝,所有例項共享),並持有對應的方法區的方法的控制代碼,這塊記憶體有一個唯一記憶體地址,棧中的a物件指向的就是這個記憶體地址。
之後你為類的成員變數賦值時,堆中的變數的值會從預設值更改為設定值(方法區中變數無值)。
如果此時在例項化一個新的類(A a2=new A();),此時方法區中已經有一個A類的class,所以不會在建立一個A.class,但是此時會在堆中開闢一塊新的空間並且將這個類的非靜態成員拷貝並持有對應的方法區類的方法的控制代碼,這塊記憶體空間標註一個新的記憶體地址。

此時,棧中a指向的是堆中第一個類的記憶體地址,a2指向的是堆中的第二個類的記憶體地址,而堆中這兩塊記憶體地址指向的是同一個方法區的class檔案。
所以棧中物件要麼存的是一個記憶體地址(引用)要麼就是一個具體的值,存放的是一個具體值的話他就是一個基本變數。

注意:堆中的非靜態成員變數存放的具體值,並不會指向方法區中非靜態成員的地址,所以非靜態成員的值與方法區無關,但是靜態成員變數的話是存在於方法區的,堆中不能持有。 具體過程見下圖:

面向物件的特徵:
封裝,整合,多型,抽象。
封裝:隱藏物件功能實現的細節。
1:私有化類中的屬性,外部的類不能訪問本類的成員變數(需要自己設定訪問修飾符)。
2:提供給外部類造作的getter與setter方法
3:提供給外部成員呼叫方法使用Public修飾。
繼承:子類繼承父類的成員變數。
1:繼承後子類操作的是屬於子類的變數,不影響父類的變數值。
2:supper指向的是父類的引用,this是本身的引用。
3:如果子類建立一個成員變數與父類成員變數同名時變數不會被覆蓋。
4:子類例項化時會先例項化父類,因為例項化子類時構造器會有一個隱式的super();這是呼叫父類的構造器。
5:子類繼承父類的所有屬性與方法,同名屬性不覆蓋。同名方法會覆蓋(重寫),不過只能覆蓋例項方法,靜態方法與finall除外。
6:final不能被重寫,類不能被繼承。
7:靜態方法又叫做類方法,該方法需要類的名稱訪問。該方法只屬於這個類,不屬於:某個類物件。
8:static修飾的方法中必須呼叫靜態的方法和使用靜態變數。

多型:就是一個事物的多種表現形態。
表現形式:重寫(子類重寫父類的方法)、過載(同一個類方法名相同引數不同,與返回值無關)。
重寫與過載沒什麼關係,只是名字有點相似而已,有些面試會問到。
抽象:理論,思想,生活中不能具體描述出來。
具體表現形式:抽象類,介面。
抽象類:使用abstract關鍵字修飾的類,就是抽象類。
1:語法:public abstract class 抽象類名稱。
2:抽象類不可以被例項化,但是有建構函式,因為還需要初始化。
3: 抽象類中可以定義抽象方法與普通方法。
4: 含有抽象方法得類一定是抽象類或者是介面。
5: 抽象類天生就是需要被繼承的,否則無意義,抽象類也可以繼承抽象類,它提供方法模板(抽象方法),抽象方法不可以使用private修飾,也沒有意義。
6: 抽象類就是模板設計模式,提供模板,子類具體去實現

介面:介面是一個特殊的抽象類,不能有建構函式,不能有成員變數
1:介面中所有成員,常量,方法都是public
2:因為不能初始化,所以介面中定義方法都是抽象方法
3:介面是必須讓實現類實現介面中所有定義的抽象類的
4:jdk1.8版本及以上可以在介面中使用static與default關鍵字定義實現方法
作用:限定實現類必須含有的方法。