Java編程陷阱-類成員初始化

來源:互聯網
上載者:User

如果你忽略Java的細節,恐怕你的代碼會充滿bug,下面討論關於類成員初始化問題。

第一類,初始化成員變數在構造方法之前

主要參考TIJ中的代碼,來說明問題!!

1. 建立一個類Tag

package mark.initial;<br />public class Tag {</p><p>/**<br /> * 構造方法<br /> *<br /> * @param maker<br /> */<br />public Tag(int maker) {<br />System.out.println("tag(" + maker + ")");<br />}<br />}<br /> 

2. 建立一個類Card

package mark.initial;<br />public class Card {</p><p>Tag tag1 = new Tag(1);</p><p>/**<br /> * 構造方法<br /> */<br />public Card() {<br />System.out.println("card()");<br />Tag tag3 = new Tag(33);<br />}</p><p>Tag tag2 = new Tag(2);</p><p>/**<br /> * 成員方法<br /> */<br />public void f() {<br />System.out.println("f()");<br />}</p><p>Tag tag3 = new Tag(3);<br />}<br /> 

3. 建立測試類別

package mark.initial;<br />public class TestInitial {</p><p>public static void main(String[] args) {<br />Card c = new Card();<br />c.f();<br />}<br />}<br /> 

看結果之前,簡單分析一下。在Card中,到處都有Tag對象,看起來比較亂。其實這是故意的,我們知道類的成員變數會被初始化為預設值比如引用初始化為null,int預設為0,float預設為0.0等,如果你沒有指定這些成員變數的值時。

在測試類別TestInitial中,new一個Card,這樣就會初始化它的成員變數tag1、tag2、tag3先為null,(由於我們手動將這些成員變數賦予新值即new該對象),然後會指向堆裡面的對象。最後Card調用自己的建構函式,所以結果如下所示:

tag(1)<br />tag(2)<br />tag(3)<br />card()<br />tag(33)<br />f() 

第二類,成員變數初始化在構造方法之後

子類成員變數初始化,父類Linux,子類User重寫父類的print()方法,並在該方法中改變成員變數name值。

package my.test;public class Linux {int size = 10;String name = "Linux";/** * 構造方法 */public Linux() {System.out.println("I'm Linux OS!");print();}public void print() {System.out.println("父類Linux--print()");}}class User extends Linux {String name = "ubuntu";@Overridepublic void print() {name = "ubuntu10.10";System.out.println("子類User--print()");}}

測試代碼:

class TestLinux {</p><p>public static void main(String[] args) {<br />User user = new User();<br />System.out.println(user.name);<br />}<br />}  

在main方法中建立User執行個體對象user,User會調用自己的構造方法,然而我們知道子類在其構造方法中會先調用父類的構造方法,這樣一來User的父類Linux會執行自己的構造方法,從而調用print()方法,由於子類User覆寫父類方法,所以調用的是子類的print()方法。將name的值變為ubuntu10.10,構造方法執行完畢,開始初始化User的成員變數即name為ubuntu,那麼列印結果就是如下所示:

I'm Linux OS!子類User--print()ubuntu 

第三類,其實這是第二類的另一個執行個體

下面是單例模式:

package my.test;<br />public class ClassloadTest {<br />// 聲明類成員變數並建立該對象<br />static final ClassloadTest test = new ClassloadTest();</p><p>public static int a = 5;<br />public static int b = 8;</p><p>/**<br /> * 私人構造方法<br /> */<br />private ClassloadTest() {<br />a++;<br />b++;<br />}</p><p>/**<br /> * 擷取類的執行個體對象<br /> *<br /> * @return ClassloadTest執行個體對象<br /> */<br />public static ClassloadTest getInstance() {<br />return test;<br />}<br />} 

好了,看懂上述代碼之後,看看測試代碼:

class Test {<br />public static void main(String[] args) {<br />System.out.println("a = " + ClassloadTest.getInstance().a);<br />System.out.println("b = " + ClassloadTest.getInstance().b);<br />}<br />} 

在公布答案之前,大部分人都會很自信的說結果是下面的樣子:

a = 6<br />b = 9 

呵呵,你太衝動啦!!!回答錯誤,好好想一想吧!!

下面這句代碼是建立ClassloadTest 對象 test:

// 聲明類成員變數並建立該對象<br />static final ClassloadTest test = new ClassloadTest(); 

在測試類別中,獲得類的執行個體即建立對象,就會調用構造方法,其實發生的時間是這樣子的:

<1> 初始化test為null,a=0,b=0,這裡的值是預設賦值,不是你手動所賦的值5和8

<2> test = new ClassloadTest(),會調用構造方法,從而使a=1,b=1

<3> 順序執行代碼,靜態變數a=5,b=8,那麼原來的a=1,b=1就被覆蓋掉

ok,執行結果應該是:

a = 5<br />b = 8 

如果,改變代碼中static final ClassloadTest test = new ClassloadTest();的位置結果會不一樣的。現在改變ClassloadTest類如下:

package my.test;<br />public class ClassloadTest {</p><p>public static int a = 5;<br />public static int b = 8;</p><p>// 聲明類成員變數並建立該對象<br />static final ClassloadTest test = new ClassloadTest();</p><p>/**<br /> * 私人構造方法<br /> */<br />private ClassloadTest() {<br />a++;<br />b++;<br />}</p><p>/**<br /> * 擷取類的執行個體對象<br /> *<br /> * @return ClassloadTest執行個體對象<br /> */<br />public static ClassloadTest getInstance() {<br />return test;<br />}<br />} 

還是上使用上面的測試方法,結果如下:

a = 6<br />b = 9<br /> 

分析如下:

<1> 初始化test為null,a=0,b=0,這裡的值是預設賦值,不是你手動所賦的值5和8

<2> a=5,b=8

<3> test = new ClassloadTest(),會調用構造方法,從而使a=6,b=9

小結:

說到這裡,我們至少明白下面的道理(針對類成員變數):

<1> 物件導向編程,也需要考慮聲明變數的順序

<2> Java中的聲明和初始化不是原子操作,即他們不是一體化的,也就是說聲明後它會有一個預設值,初始化值是可以手動賦值的。

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.