分類: java 首先我們來看下面這段代碼: publicclassTest1 { String a = '123'; publicstaticvoidchange(Test1 test) { test.a='abc'; } publicstaticvoidmain(String[] args) { Test1 test1=new Test1(); System.out.println(test1.a); change(test1); System.out.println(test1.a); } }結(jié)果輸出123 abc 相信大家都能做對這道題目。Java是按引用傳遞的,在函數(shù)里面可以修改對象的值,。我們再看下面的代碼: publicclassTest2{publicstaticvoidmain(String[] args) { String str = '123'; System.out.println(str); change(str); System.out.println(str); } publicstaticvoidchange(String str){ str = 'abc'; } } 你認(rèn)為會輸出多少,?總之我周圍的好幾個人都說會輸出123 abc。因?yàn)樵贘ava中String不是基本數(shù)據(jù)類型,,會傳遞引用,,所以在change方法里面可以修改str的值。 誤區(qū)1: 有人說可能是這里String定義的方式有問題,因?yàn)檫@里的定義方式String str = “123”,,可能存在問題,,java會將其存放在字符串常量池中(當(dāng)再次聲明一個同樣內(nèi)容的字符串時將會使用字符串常量池中原來的那個內(nèi)存,而不會重新分配) java String str = new String(“123”); str是指向堆區(qū)的內(nèi)存會傳遞引用,??墒墙Y(jié)果依然打印 123 123 誤區(qū)2:String是不可變的 還有人查看String文檔發(fā)現(xiàn) Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared.For example: String str = 'abc';is equivalent to: char data[] = {'a', 'b', 'c'}; String str = new String(data);可以看到官方文檔解釋了因?yàn)镾tring是不可以改的。所以有人認(rèn)為這就是在函數(shù)里面無法修改String值得原因,。 請看下面的代碼 publicclassTest3{publicstaticvoidmain(String[] args) { String str = new String('123'); str = new String('abc'); System.out.println(str); } }按照這種理解,,這里的String應(yīng)該還打印123而不是abc。顯然這不是瞎扯么,。 文檔中說StringBuffer是可變的我們用StringBuffer試試 publicclassTest4{publicstaticvoidmain(String[] args) { StringBuffer str = new StringBuffer('123'); System.out.println(str); change(str); System.out.println(str); } publicstaticvoidchange(StringBuffer str){ str = new StringBuffer('abc'); // str.append(abc); } }依然打印123 123,,可見根本不是這個原因,并且對可變不可變的理解有誤,。 傳遞引用,? 于是疑問就產(chǎn)生了,傳引用到底是什么意思,? 在Java里面?zhèn)鬟f引用到底是什么意思,?實(shí)質(zhì)上就是將該變量的地址傳遞了過來,,這個角度來看實(shí)際上也是按值傳遞的。 上面的內(nèi)存圖表示new一個變量的時候真正的對象其實(shí)在堆區(qū),,棧上保存了一個指向堆區(qū)存放該對象內(nèi)存的地址,。于是在函數(shù)調(diào)用的時候傳遞引用也就是傳遞這個地址值得一個拷貝。通過這個地址值可以修改這個地址所在堆區(qū)的內(nèi)容,。切記,,傳遞的這個地址是按值傳遞的。在函數(shù)里面修改這個值得結(jié)果就是失去對堆區(qū)對象的指向,。函數(shù)調(diào)用完成后對象沒有任何影響,。像代碼1那樣,傳遞的test1對象的地址,,因此test1對象在堆區(qū)的值都可以修改,,str是他的屬性當(dāng)然也可以修改。 看下面的代碼 publicclassTest5{publicstaticvoidmain(String[] args) { Object o = new Object(); System.out.println(o); change(o); System.out.println(o); } publicstaticvoidchange(Object o){ o = null; } }調(diào)用change函數(shù)將o置為null,,對o對象毫無作用,再次打印o的值照樣有值,,因?yàn)閭鬟f的只是o對象地址的一個拷貝,,在函數(shù)里面修改該變量的值對外面毫無影響。 因此,,注意Java中所說的按引用傳遞實(shí)質(zhì)上是傳遞該對象的地址,,該地址其實(shí)是按值傳遞的,通過這個地址可以修改其指向內(nèi)存處對象的值,。改變該地址的值毫無意義,,只會失去對真實(shí)對象的掌控。 再來解釋一下產(chǎn)生上面誤區(qū)2的原因,。文檔中說String不可變StringBuffer可變的意思是堆區(qū)的那片內(nèi)存的可變性,。 // added at 2015年11月2日10:44:27 附上stackoverflow上關(guān)于java傳值還是傳引用的回答:Is Java “pass-by-reference” or “pass-by-value”? Java is always pass-by-value. Unfortunately, they decided to call pointers references, thus confusing newbies. Because those references are passed by value. Java一直是值傳遞。不幸的是,,他們決定把指針叫做引用,,因此新人總是被搞暈。因?yàn)檫@些引用也是通過值傳遞的 |
|