Java 中引用傳遞還是值傳遞
阿新 • • 發佈:2019-02-20
【一:搞清楚 基本型別 和 引用型別的不同之處】
int num = 10;
String str = "hello";
如圖所示,num是基本型別,值就直接儲存在變數中。而str是引用型別,變數中儲存的只是實際物件的地址。一般稱這種變數為”引用”,引用指向實際物件,實際物件中儲存著內容。
【二:搞清楚賦值運算子(=)的作用】
num = 20;
str = "java";
對於基本型別 num ,賦值運算子會直接改變變數的值,原來的值被覆蓋掉。對於引用型別 str,賦值運算子會改變引用中所儲存的地址,原來的地址被覆蓋掉。但是原來的物件不會被改變(重要)。如上圖所示,”hello” 字串物件沒有被改變。(沒有被任何引用所指向的物件是垃圾,會被垃圾回收器回收)
【三:呼叫方法時發生了什麼?引數傳遞基本上就是賦值操作。】
//第一個例子:基本型別
void foo(int value) {
value = 100;
}
foo(num); // num 沒有被改變
//第二個例子:沒有提供改變自身方法的引用型別
void foo(String text) {
text = "windows";
}
foo(str); // str 也沒有被改變
//第三個例子:提供了改變自身方法的引用型別
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"。
重點理解為什麼,第三個例子和第四個例子結果不同?
下面是第三個例子的圖解:
builder.append(“4”)之後
下面是第四個例子的圖解:
builder = new StringBuilder(“ipad”); 之後
- = 是賦值操作(任何包含=的如+=、-=、 /=等等,都內含了賦值操作)。不再是你以前理解的數學含義了,而+ - * /和 = 在java中更不是一個級別,換句話說, = 是一個動作,一個可以改變記憶體狀態的操作,一個可以改變變數的符號,而+ - * /卻不會。這裡的賦值操作其實是包含了兩個意思:1、放棄了原有的值或引用;2、得到了 = 右側變數的值或引用。Java中對 = 的理解很重要啊!!可惜好多人忽略了,或者理解了卻沒深思過。
- 對於基本資料型別變數,= 操作是完整地複製了變數的值。換句話說,“=之後,你我已無關聯”;至於基本資料型別,就不在這科普了。
- 對於非基本資料型別變數,= 操作是複製了變數的引用。換句話說,“嘿,= 左側的變數,你丫別給我瞎動!咱倆現在是一根繩上的螞蚱,除非你再被 = 一次,放棄現有的引用!!上面說了 = 是一個動作,所以我把 = 當作動詞用啦!!”。
- 引數本身是變數,引數傳遞本質就是一種 = 操作。引數是變數,所有我們對變數的操作、變數能有的行為,引數都有。所以把C語言裡引數是傳值啊、傳指標啊的那套理論全忘掉,引數傳遞就是 = 操作。
Java只有一種引數傳遞方式:那就是按值傳遞,即Java中傳遞任何東西都是傳值
如果引數是基本型別,傳遞的是基本型別的字面量值的拷貝。
如果引數是引用型別,傳遞的是該參量所引用的物件在堆中地址值的拷貝