通常認爲,java內的基礎類型數據傳遞都是值傳遞. java中實例對象的傳遞是引用傳遞。值傳遞是對基本型變量而言的,傳遞的是該變量的一個副本,改變副本不影響原變量。引用傳遞通常是對於對象型變量而言的,傳遞的是該對象地址的一個副本, 並非原對象自己 。java
首先,不要糾結於 Pass By Value 和 Pass By Reference 的字面上的意義,不然很容易陷入所謂的「一切傳引用其實本質上是傳值」這種並不能解決問題無心義論戰中。
更況且,要想知道Java究竟是傳值仍是傳引用,起碼你要先知道傳值和傳引用的準確含義吧?但是若是你已經知道了這兩個名字的準確含義,那麼你本身就能判斷Java究竟是傳值仍是傳引用。
這就好像用大學的名詞來解釋高中的題目,對於初學者根本沒有任何意義。windows
一:搞清楚 基本類型 和 引用類型的不一樣之處app
int num = 10; String str = "hello";
如圖所示,num是基本類型,值就直接保存在變量中。而str是引用類型,變量中保存的只是實際對象的地址。通常稱這種變量爲"引用",引用指向實際對象,實際對象中保存着內容。iphone
二:搞清楚賦值運算符(=)的做用ui
num = 20; str = "java";
對於基本類型 num ,賦值運算符會直接改變變量的值,原來的值被覆蓋掉。
對於引用類型 str,賦值運算符會改變引用中所保存的地址,原來的地址被覆蓋掉。可是原來的對象不會被改變(重要)。
如上圖所示,"hello" 字符串對象沒有被改變。(沒有被任何引用所指向的對象是垃圾,會被垃圾回收器回收)
三:調用方法時發生了什麼?參數傳遞基本上就是賦值操做。
第一個例子:基本類型code
void foo(int value) { value = 100; } foo(num); // num 沒有被改變
第二個例子:沒有提供改變自身方法的引用類型對象
void foo(String text) { text = "windows"; } foo(str); // str 也沒有被改變
第三個例子:提供了改變自身方法的引用類型blog
StringBuilder sb = new StringBuilder("iphone"); void foo(StringBuilder builder) { builder.append("4"); } foo(sb); // sb 被改變了,變成了"iphone4"。
第四個例子:提供了改變自身方法的引用類型,可是不使用,而是使用賦值運算符。圖片
StringBuilder sb = new StringBuilder("iphone"); void foo(StringBuilder builder) { builder = new StringBuilder("ipad"); } foo(sb); // sb 沒有被改變,仍是 "iphone"。
重點理解爲何,第三個例子和第四個例子結果不一樣?ip
下面是第三個例子的圖解:
builder.append("4")以後
下面是第四個例子的圖解:
builder = new StringBuilder("ipad"); 以後