1.引用的本質
比如示例代碼:
該代碼內存及引用創建過程
(1)
Object obj=new Object();
在堆內存創建object對象,對象地址為40f1。然后在棧內存創建引用,引用也是有地址的,該地址所在堆內存存儲的數據被賦予為40f1,指向創建的object。
(2)
obj=new Object();
由于new關鍵字,在堆內存中創建新的object對象,對象地址為40fb。然后把引用存儲的數據重新賦予為新的object地址
綜上可得:
2.引用傳遞的本質
先看一段代碼:
注意:輸出結果為 :Hello而不是World
調用過程分析:
- (1)在棧內存中為testString()分配一段內存空間,然后再在堆內存中創建Holle字符串,地址為5A1c,接在來在棧內存中穿件String類型的引用,值為5A1C,指向holle字符串。
- (2)調用changeString函數,然后為形參引用開辟內存空間將實參的值傳遞給形參,這樣形參的引用也指向了堆內存中的Holle字符串。(注意在棧內存中實參和形參兩個引用str的地址是不同的)
- (3)在堆內存中為字符串“World”新開創內存空間地址為5AB6,并把changeString函數中的形參引用str指向新的字符串。此時形參str的值變為5AB5。
完成了changeString函數后,形參引用被棧內存回收了,響應的指向也被回收了。Wolrd也因為沒有引用指向它,所以也會被響應地被垃圾回收器回收掉。
最后只有原來的引用還在所以打印結果為:Holle
其他引用類型傳遞以此類推:
例如:輸出結果AAA
總結:
3.改變對象的值
另一種情況(輸出結果為BBB)
調用過程分析:
- (1)在棧內存中為testPerson()分配一段內存空間,然后再在堆內存中創建person對象,地址為5B1c,同時也創建字符串類型對象name,地址為5A8F,接在來在棧內存中穿件person類型的引用P,值為5B1C,指向創建person對象。
-
(2)調用changePerson函數,然后為形參引用開辟內存空間將實參的值傳遞給形參,這樣形參的引用p也指向了堆內存中的Person對象。(注意在棧內存中實參和形參兩個引用p的地址是不同的)
- (3)在堆內存中為字符串“BBB”新開創內存空間地址為5B46,并把changePerson函數中的形參引用str中的name引用指向新的字符串。person中name引用的值變為5B46,指向 。
完成了changePerson函數后,相應的引用指向還在testPerson()方法里。所以并不會被垃圾回收器回收掉。
所以打印結果為:“BBB”
再另一種情況:
輸出結果仍舊為Holle
- (1)在棧內存中為testString01()分配一段內存空間,然后再在堆內存中創建Holle字符串,地址為5A1c,接在來在棧內存中穿件String類型的引用,值為5A1C,指向holle字符串。
- (2)調用changeString01函數,然后為形參引用開辟內存空間將實參的值傳遞給形參,這樣形參的引用也指向了堆內存中的Holle字符串。(注意在棧內存中實參和形參兩個引用str的地址是不同的)
- (3)調用replaceall方法在堆內存中為字符串“World”新開創內存空間地址為5A39,然而并沒有引用指向它。
完成了changeString01函數后,形參引用被棧內存回收了,響應的指向也被回收了。Wolrd也因為沒有有引用指向它,所以也會被響應地被垃圾回收器回收掉。
最后只有原來的引用還在所以打印結果為:Holle
再看一個案例:
與上面例子不同的是:
str=str.replaceAll("Hello", "World");
在這里由于等于號的存在,將形參指向World,形參值為5A39,changeString02完成后形參引用被回收,引用指向消失,但對world的引用被函數返回了,由于
str=changeString02(str);
的存在,TestString02中的str引用重新指向5A39,所以輸出為world