JAVA引用和對(duì)象的關(guān)系,還有值傳遞_第1頁
JAVA引用和對(duì)象的關(guān)系,還有值傳遞_第2頁
JAVA引用和對(duì)象的關(guān)系,還有值傳遞_第3頁
JAVA引用和對(duì)象的關(guān)系,還有值傳遞_第4頁
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Java對(duì)象及其引用關(guān)鍵字: java對(duì)象引用 Java對(duì)象及其引用 關(guān)于對(duì)象與引用之間的一些基本概念。 初學(xué)Java時(shí),在很長(zhǎng)一段時(shí)間里,總覺得基本概念很模糊。后來才知道,在許多Java書中,把對(duì)象和對(duì)象的引用混為一談??墒?,如果我分不清對(duì)象與對(duì)象引用, 那實(shí)在沒法很好地理解下面的面向?qū)ο蠹夹g(shù)。把自己的一點(diǎn)認(rèn)識(shí)寫下來,或許能讓初學(xué)Java的朋友們少走一點(diǎn)彎路。 為便于說明,我們先定義一個(gè)簡(jiǎn)單的類:class Vehicle int passengers; int fuelcap; int mpg; 有了這個(gè)模板,就可以用它來創(chuàng)建對(duì)象: Vehicle veh1 = new Vehicle()

2、; 通常把這條語句的動(dòng)作稱之為創(chuàng)建一個(gè)對(duì)象,其實(shí),它包含了四個(gè)動(dòng)作。 1)右邊的“new Vehicle”,是以Vehicle類為模板,在堆空間里創(chuàng)建一個(gè)Vehicle類對(duì)象(也簡(jiǎn)稱為Vehicle對(duì)象)。 2)末尾的()意味著,在對(duì)象創(chuàng)建后,立即調(diào)用Vehicle類的構(gòu)造函數(shù),對(duì)剛生成的對(duì)象進(jìn)行初始化。構(gòu)造函數(shù)是肯定有的。如果你沒寫,Java會(huì)給你補(bǔ)上一個(gè)默認(rèn)的構(gòu)造函數(shù)。3)左邊的“Vehicle veh1”創(chuàng)建了一個(gè)Vehicle類引用變量。所謂Vehicle類引用,就是以后可以用來指向Vehicle對(duì)象的對(duì)象引用。 4)“=”操作符使對(duì)象引用指向剛創(chuàng)建的那個(gè)Vehicle對(duì)象。 我們可以

3、把這條語句拆成兩部分:Vehicle veh1; veh1 = new Vehicle(); 效果是一樣的。這樣寫,就比較清楚了,有兩個(gè)實(shí)體:一是對(duì)象引用變量,一是對(duì)象本身。 在堆空間里創(chuàng)建的實(shí)體,與在數(shù)據(jù)段以及棧空間里創(chuàng)建的實(shí)體不同。盡管它們也是確確實(shí)實(shí)存在的實(shí)體,但是,我們看不見,也摸不著。不僅如此,我們仔細(xì)研究一下第二句,找找剛創(chuàng)建的對(duì)象叫什么名字?有人說,它叫“Vehicle”。不對(duì),“Vehicle”是類(對(duì)象的創(chuàng)建模板)的名字。 一個(gè)Vehicle類可以據(jù)此創(chuàng)建出無數(shù)個(gè)對(duì)象,這些對(duì)象不可能全叫“Vehicle”。 對(duì)象連名都沒有,沒法直接訪問它。我們只能通過對(duì)象引用來間接訪問對(duì)象。

4、 為了形象地說明對(duì)象、引用及它們之間的關(guān)系,可以做一個(gè)或許不很妥當(dāng)?shù)谋扔鳌?duì)象好比是一只很大的氣球,大到我們抓不住它。引用變量是一根繩, 可以用來系汽球。 如果只執(zhí)行了第一條語句,還沒執(zhí)行第二條,此時(shí)創(chuàng)建的引用變量veh1還沒指向任何一個(gè)對(duì)象,它的值是null。引用變量可以指向某個(gè)對(duì)象,或者為null。 它是一根繩,一根還沒有系上任何一個(gè)汽球的繩。執(zhí)行了第二句后,一只新汽球做出來了,并被系在veh1這根繩上。我們抓住這根繩,就等于抓住了那只汽球。 再來一句:Vehicle veh2;就又做了一根繩,還沒系上汽球。如果再加一句: veh2 = veh1; 系上了。這里,發(fā)生了復(fù)制行為。但是,要說

5、明的是,對(duì)象本身并沒有被復(fù)制,被復(fù)制的只是對(duì)象引用。結(jié)果是,veh2也指向了veh1所指向的對(duì)象。兩根繩系的是同一只汽球。 如果用下句再創(chuàng)建一個(gè)對(duì)象: veh2 = new Vehicle();則引用變量veh2改指向第二個(gè)對(duì)象。從以上敘述再推演下去,我們可以獲得以下結(jié)論:(1)一個(gè)對(duì)象引用可以指向0個(gè)或1個(gè)對(duì)象(一根繩子可以不系汽球,也可以系一個(gè)汽球); (2)一個(gè)對(duì)象可以有N個(gè)引用指向它(可以有N條繩子系住一個(gè)汽球)。 如果再來下面語句: veh1 = veh2; 按上面的推斷,veh1也指向了第二個(gè)對(duì)象。這個(gè)沒問題。問題是第一個(gè)對(duì)象呢?沒有一條繩子系住它,它飛了。多數(shù)書里說,它被Java

6、的垃圾回收機(jī)制回收了。 這不確切。正確地說,它已成為垃圾回收機(jī)制的處理對(duì)象。至于什么時(shí)候真正被回收,那要看垃圾回收機(jī)制的心情了。 由此看來,下面的語句應(yīng)該不合法吧?至少是沒用的new Vehicle(); 不對(duì)。它是合法的,而且可用的。譬如,如果我們僅僅為了打印而生成一個(gè)對(duì)象,就不需要用引用變量來系住它。最常見的就是打印字符串:System.out.println(“I am Java!”); 字符串對(duì)象“I am Java!”在打印后即被丟棄。有人把這種對(duì)象稱之為臨時(shí)對(duì)象。對(duì)象與引用的關(guān)系將持續(xù)到對(duì)象回收。 Java對(duì)象及引用 Java對(duì)象及引用是容易混淆卻又必須掌握的基礎(chǔ)知識(shí),本章闡述Ja

7、va對(duì)象和引用的概念,以及與其密切相關(guān)的參數(shù)傳遞。 先看下面的程序:StringBuffer s; s = new StringBuffer(Hello World!); 第一個(gè)語句僅為引用(reference)分配了空間,而第二個(gè)語句則通過調(diào)用類(StringBuffer)的構(gòu)造函數(shù)StringBuffer(String str)為類生成了一個(gè)實(shí)例(或稱為對(duì)象)。這兩個(gè)操作被完成后,對(duì)象的內(nèi)容則可通過s進(jìn)行訪問在Java里都是通過引用來操縱對(duì)象的。 Java對(duì)象和引用的關(guān)系可以說是互相關(guān)聯(lián),卻又彼此獨(dú)立。彼此獨(dú)立主要表現(xiàn)在:引用是可以改變的,它可以指向別的對(duì)象,譬如上面的s,你可以給它另外的

8、對(duì)象,如:s = new StringBuffer(Java); 這樣一來,s就和它指向的第一個(gè)對(duì)象脫離關(guān)系。從存儲(chǔ)空間上來說,對(duì)象和引用也是獨(dú)立的,它們存儲(chǔ)在不同的地方,對(duì)象一般存儲(chǔ)在堆中,而引用存儲(chǔ)在速度更快的堆棧中。 引用可以指向不同的對(duì)象,對(duì)象也可以被多個(gè)引用操縱,如:StringBuffer s1 = s; 這條語句使得s1和s指向同一個(gè)對(duì)象。既然兩個(gè)引用指向同一個(gè)對(duì)象,那么不管使用哪個(gè)引用操縱對(duì)象,對(duì)象的內(nèi)容都發(fā)生改變,并且只有一份,通過s1和s得到的內(nèi)容自然也一樣,(String除外,因?yàn)镾tring始終不變,String s1=”AAAA”; String s=s1,操作s,s

9、1由于始終不變,所以為s另外開辟了空間來存儲(chǔ)s,)如下面的程序: StringBuffer s; s = new StringBuffer(Java); StringBuffer s1 = s; s1.append( World); System.out.println(s1= + s1.toString();/打印結(jié)果為:s1=Java World System.out.println(s= + s.toString();/打印結(jié)果為:s=Java World 上面的程序表明,s1和s打印出來的內(nèi)容是一樣的,這樣的結(jié)果看起來讓人非常疑惑,但是仔細(xì)想想,s1和s只是兩個(gè)引用,它們只是操縱桿而已

10、,它們指向同一個(gè)對(duì)象,操縱的也是同一個(gè)對(duì)象,通過它們得到的是同一個(gè)對(duì)象的內(nèi)容。這就像汽車的剎車和油門,它們操縱的都是車速,假如汽車開始的速度是80,然后你踩了一次油門,汽車加速了,假如車速升到了120,然后你踩一下剎車,此時(shí)車速是從120開始下降的,假如下降到60,再踩一次油門,車速則從60開始上升,而不是從第一次踩油門后的120開始。也就是說車速同時(shí)受油門和剎車影響,它們的影響是累積起來的,而不是各自獨(dú)立(除非剎車和油門不在一輛車上)。所以,在上面的程序中,不管使用s1還是s操縱對(duì)象,它們對(duì)對(duì)象的影響也是累積起來的(更多的引用同理)。 只有理解了對(duì)象和引用的關(guān)系,才能理解參數(shù)傳遞。 一般面試

11、題中都會(huì)考Java傳參的問題,并且它的標(biāo)準(zhǔn)答案是Java只有一種參數(shù)傳遞方式:那就是按值傳遞,即Java中傳遞任何東西都是傳值。如果傳入方法的是基本類型的東西,你就得到此基本類型的一份拷貝。如果是傳遞引用,就得到引用的拷貝。 一般來說,對(duì)于基本類型的傳遞,我們很容易理解,而對(duì)于對(duì)象,總讓人感覺是按引用傳遞,看下面的程序:public class ObjectRef /基本類型的參數(shù)傳遞 public static void testBasicType(int m) System.out.println(m= + m);/m=50 m = 100; System.out.println(m= +

12、 m);/m=100 /參數(shù)為對(duì)象,不改變引用的值 ? public static void add(StringBuffer s) s.append(_add); /參數(shù)為對(duì)象,改變引用的值 ? public static void changeRef(StringBuffer s) s = new StringBuffer(Java); public static void main(String args) int i = 50; testBasicType(i); System.out.println(i);/i=50 StringBuffer sMain = new StringBu

13、ffer(init); System.out.println(sMain= + sMain.toString();/sMain=init add(sMain); System.out.println(sMain= + sMain.toString();/sMain=init_add changeRef(sMain); System.out.println(sMain= + sMain.toString();/sMain=init_add 以上程序的允許結(jié)果顯示出,testBasicType方法的參數(shù)是基本類型,盡管參數(shù)m的值發(fā)生改變,但并不影響i。 add方法的參數(shù)是一個(gè)對(duì)象,當(dāng)把sMain傳

14、給參數(shù)s時(shí),s得到的是sMain的拷貝,所以s和sMain指向同一個(gè)對(duì)象,因此,使用s操作影響的其實(shí)就是sMain指向的對(duì)象,故調(diào)用add方法后,sMain指向的對(duì)象的內(nèi)容發(fā)生了改變。 在changeRef方法中,參數(shù)也是對(duì)象,當(dāng)把sMain傳給參數(shù)s時(shí),s得到的是sMain的拷貝,但與add方法不同的是,在方法體內(nèi)改變了s指向的對(duì)象(也就是s指向了別的對(duì)象,牽著氣球的繩子換氣球了),給s重新賦值后,s與sMain已經(jīng)毫無關(guān)聯(lián),它和sMain指向了不同的對(duì)象,所以不管對(duì)s做什么操作,都不會(huì)影響sMain指向的對(duì)象,故調(diào)用changeRef方法前后sMain指向的對(duì)象內(nèi)容并未發(fā)生改變。 對(duì)于ad

15、d方法的調(diào)用結(jié)果,可能很多人會(huì)有這種感覺:這不明明是按引用傳遞嗎?對(duì)于這種問題,還是套用Bruce Eckel的話:這依賴于你如何看待引用,最終你會(huì)明白,這個(gè)爭(zhēng)論并沒那么重要。真正重要的是,你要理解,傳引用使得(調(diào)用者的)對(duì)象的修改變得不可預(yù)期。 public class Test public int I,j; public void test_m(Test a) Test b=new Test(); b.i=1; b.j=2; a=b; public void test_m1(Test a ) a.i = 1; a.j =2; public static void main(String argv) Test t=new Test(); t.i=5; t.j=6; System.out.println( t.i=+ t.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論