值傳遞#
Java的方法參數傳遞是值傳遞!是值傳遞!值傳遞!!!重要的事情說三遍。
什么是值傳遞?
一個很簡單的例子:
class MethodParaTest
{
private static void swap(int a,int b)
{
int temp;
temp = a;
a = b;
b = temp;
System.out.println("swap Method : a = "+a+" , b = "+b);
}
public static void main(String[] args)
{
int a = 1,b = 2;
swap(a,b);
System.out.println("New Value : a = "+a+" , b = "+b);
}
}
運行結果:
swap Method : a = 2b = 1
New Value : a = 1b = 2
可見,原值并未發生任何變化,這是因為在調用swap方法時,出入的參數是int變量a,b的值副本而非其本身,所以在swap方法中發生的一切事情在調用結束后對原變量并未產生任何影響,而形參a,b也在方法執行完畢后被銷毀。
關于引用類型的參數傳遞#
引用類型的變量包括類、數組、接口。
所謂引用,可以想象C中的指針,在變量中之儲存引用的地址,指向被引用的對象,這里的對象可以是類的實例、數組、接口。
而發生參數傳遞時,所傳遞的是變量值得副本,在這里就是地址的副本,即將堆區存放的對象的地址傳遞給形參。
一個簡單的例子:
class ReferParaTest
{
private int a = 1;
private int b = 2;
private static void swap(ReferParaTest o)
{
int temp;
temp = o.a;
o.a = o.b;
o.b = temp;
}
public static void main(String[] args)
{
ReferParaTest o1 = new ReferParaTest();
swap(o1);
System.out.println("NEW VALUE : a = "+o1.a+" , b = "+o1.b);
}
}
運行結果
NEW VALUE : a = 2 , b = 1
o1對象的a,b成員變量成功互換,但這時發生的還是值傳遞而非引用傳遞,因為o1只是一個引用變量,系統復制了它的值,但并未復制ReferParaTest對象本身,形參o和實參o1指向堆區的同一對象,所以可對這一對象進行修改。
另一個例子
class ReferSwapTest
{
String s;
public ReferSwapTest(String s)
{
this.s = s;
}
public static void swap(ReferSwapTest a,ReferSwapTest b)
{
ReferSwapTest temp;
temp = a;
a = b;
b = temp;
}
public static void main(String[] args)
{
ReferSwapTest r1 = new ReferSwapTest("first");
ReferSwapTest r2 = new ReferSwapTest("second");
swap(r1,r2);
System.out.println("NEW VALUE : r1 = "+r1.s+" , r2 = "+r2.s);
}
}
運行結果
NEW VALUE : r1 = first , r2 = second
與第一個例子相同,對象并未發生任何變化,因為傳遞的依舊是r1,r2值得副本,而非對象本身,所以發生交換的只是形參a,b內所存儲的值,與原變量無關。
需要注意的是:#
對于引用變量的參數傳遞,可以在調用的方法中對原對象進行修改,但原引用變量的指向值不發生變化,第二個例子中在swap方法中修改了對象中的a,b的值,第三個例子說明了此時仍然發生的是值傳遞。
一個形象但可能不太恰當的比喻:
一個變量是一座房子,變量的地址是房子的地址,變量的值是房子里面的家具和其他物品。
這樣,這幾種傳遞方式就成了這樣,
- 值傳遞:去家具店買了一模一樣的家具搬到新房子里,隨便怎么折騰,老房子的家具不會發生任何變化,但如果把一張寫有存放寶箱地址的紙條(引用變量)也抄錄一份搬到新房子,那么通過這張紙條就可以找到寶箱再次折騰,這樣寶箱里的寶物就可能變了。
- 引用傳遞:直接把自己的房子給人家折騰,當然會大變樣。
- 指針傳遞:把自己房子的地址給人家,這樣,人家通過地址還是可以找到你的房子,折騰不折騰的就看心情了。