相信對不少初學java的人來講這部份內容不太容易明白,最近又看了一些java視頻,有點收穫,打算總結一下。java明確說明取消了指針,由於指針每每是再帶來方便的同時也是致使代碼不安全的根源,並且還會使得程序變得很是複雜和難以理解。java放棄指針只是在java語言中沒有明確的指針定義,實質上,每個new語句返回的都是一個指針的引用。只不過在大多數時候java不用關心如何操做這個「指針」,更不像在操做C++的指針那樣膽戰心驚,惟一要多注意的是在給函數傳遞對象的時候。因此,初學java的人沒必要花費太多精力去了解,可是對於一個真正的java程序員來講這個問題是基礎。廢話少說,直接進入正題:
java中是傳值仍是傳引用呢 ?
關於這個問題,就像光究竟是波仍是粒子的問題同樣衆說紛紜。可是咱們首先要搞清楚一點:無論java的參數類型是什麼,一概傳遞參數的副本(引用thinking in Java 中的一句話:When you're passing primitives into a method, you get a distinct copy of the primitive.When you're passing a reference into a method, you get a copy of the reference)。
java中的變量分爲如下兩類:
(1)基本類型變量(int,long,double,boolean,float, byte,char),對於這些變量,java傳遞的是值的副本(與c++相同),即把本身賦值一份傳遞,即便本身的副本變了,本身也不會改變;
(2)對象型變量。java傳遞的是引用的副本(複製指向地址的指針),而不是本身實際值的副本。爲啥這麼作呢?緣由很簡單,由於對象類型是放在堆裏邊的(new一個對象的時候其實是再堆中開闢出了一塊內存空間存放對象,在棧中存放指向對象的指針),因此訪問位於堆中的對象相對於基本類型數據來講比較慢;另外一方面是由於對象類型自己就比較大,若是採用複製對象值的方法,不只浪費內存並且速度比較慢。
在thinking in Java 中解釋是這樣的:不論是基本類型仍是對象類型,都是傳值。這種說法是把引用的副本也看做了一種「值」,也可以說的過去,可是本人仍是更同意將按值傳遞和按引用傳遞分開比較好理解。
注意:java中String類型也是對象型變量,因此它傳遞的是引用的副本。String是一個非可變類,其傳值仍是傳引用顯得沒什麼區別。html
理論說完了,下面看幾個例子:
num1:傳基本類型
java
public class Test { public static void test(boolean test) { test = !test; System.out.println("In test(boolean):test = " + test); } public static void main(String args[]) { boolean test = true; System.out.println("Before test(boolean):test = " + test); test(test); System.out.println("After test(boolean):test = " + test); } }
運行結果:
Before test(boolean):test = true
In test(boolean):test = false //傳進去的是boolean類型的副本,副本改變了可是原值不改變
After test(boolean):test = true
num2:傳對象類型node
public class Test { public static void test(StringBuffer str) { str.append(", World!"); } public static void main(String args[]) { StringBuffer string = new StringBuffer("Hello"); test(string); System.out.println(string); } }
運行結果:Hello, World! //經過引用副本找到地址,而後修改裏邊的值,即修改了對象。
num3:關於傳Stringc++
public class Test { public static void test(String str) { str = "World"; } public static void main(String args[]) { String string = "Hello"; test(string); System.out.println(string); } }
一眼看去輸出結果應該是:World程序員
可是實際的運行結果倒是:Hello,String不是按引用傳遞的嗎?難道出問題了?
翻看了一些java教程,緣由以下:
執行str = 「World」;這句的時候,系統會自動生成一個新的String對象,並把這個新對象的值設爲「World」,而後將這個對像的引用賦值給str,str是原來String的副本,改變的是副本的值,那麼就與原來的值沒有關係了。當test函數執行完畢,str隨之釋放,原來的內存地址上內容沒發生任何變化。所以輸出hello,num2中str.append(", World!");就不同了,StringBuffer是產生一塊內存空間,相關的增、刪、改操做都在其中進行,因此此句是在同一段內存上進行的,即修改了原值,str所指向的引用並無變。安全