標籤:java 按值傳遞 按引用傳遞
相信對很多初學java的人來說這個問題還是很重要,因為不同於C,C++,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是一個非可變類,其傳值還是傳引用顯得沒什麼區別。
理論說完了,下面看幾個例子:
num1:傳基本類型
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:傳物件類型
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:關於傳String
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不是按引用傳遞的嗎?難道出問題了?
查了一下,原因如下:
執行str = “World”;這句的時候,系統會自動產生一個新的String對象,並把這個新對象的值設為“World”,然後將這個對像的引用賦值給str,str是原來String的副本,改變的是副本的值,那麼就與原來的值沒有關係了。當test函數執行完畢,str隨之釋放,原來的記憶體位址上內容沒發生任何變化。因此輸出hello,num2中str.append(", World!");就不一樣了,StringBuffer是產生一塊記憶體空間,相關的增、刪、改操作都在其中進行,所以此句是在同一段記憶體上進行的,即修改了原值,str所指向的引用並沒有變。
水平有限,希望各位大神給予指正補充,Thank you!
本文出自 “開發交流,共同進步” 部落格,請務必保留此出處http://smile2015.blog.51cto.com/9250194/1629685
java中按值傳遞和按引用傳遞問題