国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Java對象創建過程補遺

2019-11-14 21:03:00
字體:
來源:轉載
供稿:網友
java對象創建過程補遺

一、static修飾的東東是屬于這個類的,是所有的該類的實例共享的,因此它們的初始化先于實例對象的初始化。

二、Java中沒有靜態構造方法,但是有靜態代碼塊。當類中同時存在靜態代碼塊和靜態成員變量聲明語句時,它們誰先執行?

答:按照類中定義的從上到下順序,誰在前面誰先執行。

三、當類中同時存在非靜態代碼塊和非靜態成員變量聲明語句時,它們誰先執行?

答:按照類中定義的從上到下順序,誰在前面誰先執行。

四、含有賦值的非靜態成員變量聲明語句,如 int v=4,其實這個語句的執行要分成兩步進行。首先創建對象時初始化變量v,此時v=0;然后在構造器中再給v賦值,也就是v=4。

五、非靜態初始化塊中的賦值語句、實例變量值初始化賦值語句,都比構造器中的賦值語句先執行。

原理如下:不管是非靜態初始化塊中的賦值語句,還是實例變量值初始化賦值語句,它們在編譯器處理后,都會被提取到構造器中,而且在構造器中原有的語句之前。

public class JavaTest{    //成員變量    int count=20;    //非靜態初始化代碼塊    {        count = 12;        System.out.PRint("占個位置而已");    }    //構造器    public JavaTest()    {        System.out.println(count);    }    public JavaTest(String name)    {        System.out.println(count);    }}

編譯后等價于:

public class JavaTest{    //成員變量    int count;    //非靜態初始化代碼塊    {        System.out.print("占個位置而已");    }    //構造器    public JavaTest()    {        count=20;//原來的成員變量賦值        count=12;//原來的初始化代碼塊賦值        System.out.println(count);    }    public JavaTest(String name)    {        count=20;//原來的成員變量賦值        count=12;//原來的初始化代碼塊賦值        System.out.println(count);    }}

六、“Java對象是由構造器創建的”這句話是錯誤的。構造器只是負責對Java對象的實例變量執行初始化而已,就像前面的三、四、五點所提及的。在執行構造器代碼之前,該實例對象所占的內存已經被分配下來了,這些內存都默認是空值——對于基本類型的變量,默認的空值就是0、0.0或者false;對于引用類型的變量,默認的控制就是Null。看看下面的代碼,分析一下結果是什么:

class base{    private int i = 2;    public Base()    {        這里是1處
        this.display();    }    public void display()    {        System.out.println(i);    }}class Derived extends base{    private int i = 22;    public Derived()    {        i = 222;    }    public void display()    {        System.out.println(i);    }}public class Test{    public static void main(String[] args)    {        new Derived();    }}

問題一:Derived對象的實例中有幾個”i“實例變量? 說只有一個的同學,請自己去面壁

問題二:代碼中的紅色的1處,所指的“this”是誰?是base的實例還是Derived的實例?  答案是 Derived

問題三:代碼中的紅色1處,“this.display(); ”調用的是哪個類里面的display方法?       答案是 Derived

問題四:執行Test后輸出是2?22?還是222?   答案是 0

七、編譯器在處理成員變量和方式時是有區別的。當子類和父類存在同名的成員變量時,實際是各自擁有一個名字相同的成員變量;當子類中有個方法和父類簽名相同的時候,實際是子類對父類中該方法的重寫,這個時候通過子類的實例調用這個名稱的方法將始終是子類的方法,哪怕你把子類強制轉換成父類。這么說有點迷糊,直接往下看:

class base{    private int i = 2;    public Base()    {        this.display();    }    public void display()    {        System.out.println("我是父類"+i);    }}class Derived extends base{    private int i = 22;    public Derived()    {        i = 222;    }    public void display()    {        System.out.println("我是子類"+i);    }}

情況一:

Base b=new Base()

b.count :肯定是2,因為當前對象是父類的實例

b.display():肯定是調用父類的方法,因為當前是父類的實例

情況二:

Derived d=new Derived();

b.count: 肯定是22,因為當前對象是子類的實例,子類自己有個成員變量叫“i”干嘛拿父類的

b.display():子類的方法

情況三:

Base bd=new Derived();

b.count:肯定是2,因為當前子類是被向上轉換了,不得不拿父類的“i”

b.display():還是子類的方法,向上轉換不能太過分了,子類已經重寫的方法不能再反悔了。要想調用父類的同名方法,還得用這種方式:super.display()

情況四:

Derived d=new Derived();

Base d2b=d;

b.count:肯定是2,因為當前子類是被強制類型轉換了,不得不拿父類的“i”

b.display():還是子類的方法,強制類型轉換也不能太過分了,子類已經重寫的方法不能再反悔了。要想調用父類的同名方法,還得用這種方式:super.display()

八、從內存分配的角度來看,當程序創建一個子類對象時,JVM不僅會為該類中定義的實例變量分配內存,同時也會為其父類中定義的所有實例變量分配內存,即使子類定義了與父類中同名的實例變量。如果子類中定義了與父類同名的成員變量,那么子類中的變量會隱藏父類中定義的變量,但不是完全覆蓋,只是不能直接用而已;當把子類轉換成父類的時候或者使用”super“關鍵字,就可以使用父類中的同名成員變量了。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 三亚市| 绩溪县| 讷河市| 阜城县| 潮州市| 泸定县| 广饶县| 石柱| 哈尔滨市| 惠来县| 罗定市| 历史| 鄂伦春自治旗| 海丰县| 辉县市| 文登市| 青龙| 蓝山县| 新竹市| 西昌市| 淮安市| 曲周县| 鱼台县| 崇文区| 滕州市| 乐昌市| 巴南区| 寿宁县| 太湖县| 钟祥市| 枣庄市| 寿阳县| 海原县| 报价| 高陵县| 临湘市| 西吉县| 墨玉县| 读书| 墨玉县| 祥云县|