Java函數的傳參機制
阿新 • • 發佈:2018-06-22
輸出結果 如果 傳遞 出錯 結束 arraylist 多人 判斷 方法 。如果在函數中改變了副本的地址,如new一個,那麽副本就指向了一個新的地址,此時傳入的參數還是指向原來的 地址,所以不會改變參數的值。
一
最近的一個項目,裏面各種返回void,參數用引用類型,那叫一個熟和多,但是也把我繞糊塗了。
我就打算好好理一理java的傳參機制,整理一番
二
很多人一聽Java的傳參,那一定會脫口而出,java都是值傳遞的。恭喜各位,答對了。
那麽,傳的是什麽值?
如果參數類型是原始類型,那麽傳過來的就是這個參數的一個副本,也就是這個原始參數的值,這個跟之前所談的傳值是一樣的。如果在函數中改變了副本的值不會改變原始的值.
如果參數類型是引用類型,那麽傳過來的就是這個引用參數的副本,這個副本存放的是參數的地址。如果在函數中沒有改變這個副本的地址,而是改變了地址中的 值,那麽在函數內的改變會影響到傳入的參數三
這裏我給個代碼就很好理解了1 public class ParamterTest { 2 public static void main(String[] args) { 3 List<Integer> list1 = new ArrayList<>(); 4 List<Integer> list2 = new ArrayList<>(); 5 list1.add(0);6 list2.add(0); //(1) 7 f(list1, list2); 8 System.out.println("list1 2"); 9 p(list1); 10 System.out.println("list2 2"); 11 p(list2); //(4) 12 } 13 14 public static void f(List<Integer> list1, List<Integer> list2) {15 list1.add(1); 16 list2.add(1); 17 list2 = new ArrayList<>(); //(2) 18 list1.add(2); 19 list2.add(2); 20 System.out.println("list1 1"); 21 p(list1); 22 System.out.println("list2 1"); 23 p(list2); //(3) 24 } 25 26 public static void p(List<Integer> list) { 27 for (Integer i : list) { 28 System.out.println(i); 29 } 30 } 31 }
輸出結果
list1 1 0 1 2 list2 1 2 list1 2 0 1 2 list2 2 0 1
四
要具體解釋,就是涉及到堆,棧和方法區了。
(1)list1,list2剛剛成立,都放進了 0,因為是對象的實例所以保存在堆裏面。
(2)list1,list2將自己堆的地址傳到了方法裏,因為是引用所以保存在棧裏面,並通過地址往堆裏面的實例,放進了 1。但是,此時new了一個實例,list2在棧裏面不再指向堆的實例,而是一個新的地址。
(3)list1,list2放進了2,但此處list1依然指向堆的實例,故放進了 2,而list2則是新的地址,堆的list2並沒有放進 2。
(4)方法結束,返回的結果使堆的list1,放進了 1 , 2 。list2 因為在方法內中途有新的實例, 只放進了 1 ,而沒有 2。
五
其實一直迷惑我們,是我們判斷出錯的是String ,明明是一個引用類型,卻是基本類型的特性,因為String 實際上是[]char,具體不細說,我就丟個代碼,讓大家跑跑吧。
public class ParamterStringTest { public static void main(String[] args) { String s1 = "a"; String s2 = "a"; f(s1, s2); System.out.println("s1 2"); p(s1); System.out.println("s2 2"); p(s2); } public static void f(String s1, String s2) { s1 = "b"; s2 = "b"; System.out.println("s1 1"); p(s1); System.out.println("s2 1"); p(s2); } public static void p(String s) { System.out.println(s); } }
同理,相應的Interge等包裝類。
Java函數的傳參機制