方法在調(diào)用的時候參數(shù)是如何傳遞的呢?其實(shí)在調(diào)用的時候參數(shù)傳遞給方法,這個過程就是賦值的過程,參數(shù)傳遞和“賦值規(guī)則”完全相同,只不過參數(shù)傳遞在代碼上看不見“=”運(yùn)算符。我們先來深入的研究一下“賦值規(guī)則”吧!
public class AssignmentTest {
public static void main(String[] args) {
//基本數(shù)據(jù)類型
int a = 10;
int b = a; //a賦值給b,a把什么給了b?
//引用數(shù)據(jù)類型
Bird bird1 = new Bird("polly");
//bird1賦值給bird2,bird1把什么給了bird2?
Bird bird2 = bird1;
}
}
class Bird {
String name;
public Bird(){}
public Bird(String _name){
name = _name;
}
}
在以上程序當(dāng)中,有兩個疑問,第一個:a賦值給b,a把什么給了b?第二個:bird1賦值給bird2,bird1把什么給了bird2?
其實(shí)a,b,bird1,bird2就是4個普通的變量,唯一的區(qū)別只是a和b都是基本數(shù)據(jù)類型的變量,bird1和bird2都是引用數(shù)據(jù)類型的變量(或者說都是引用),a變量中保存的那個“值”是10,bird1變量中保存的那個“值”是0x8888(java對象內(nèi)存地址),本質(zhì)上來說10和0x8888都是“值”,只不過一個“值”是整數(shù)數(shù)字,另一個“值”是java對象的內(nèi)存地址,大家不要把內(nèi)存地址特殊化,它也是一個普通的值。
那么“賦值”是什么意思呢,顧名思義,賦值就是把“值”賦上去。a賦值給b,本質(zhì)上不是把a(bǔ)給了b,而是把a(bǔ)變量中保存的“值10”復(fù)制了一份給了b。bird1賦值給bird2本質(zhì)上不是把bird1給了bird2,而是把bird1變量中保存的“值0x8888”復(fù)制了一份給了bird2。請看以下內(nèi)存圖的變化:
圖9-33:賦值原理圖
通過以上內(nèi)存圖我們可以看出“賦值”運(yùn)算的時候?qū)嶋H上和變量的數(shù)據(jù)類型無關(guān),無論是基本數(shù)據(jù)類型還是引用數(shù)據(jù)類型,一律都是將變量中保存的“值”復(fù)制一份,然后將復(fù)制的這個“值”賦上去。他們的區(qū)別在于,如果是基本數(shù)據(jù)類型則和堆內(nèi)存當(dāng)中的對象無關(guān),如果是引用數(shù)據(jù)類型由于傳遞的這個值是java對象的內(nèi)存地址,所以會導(dǎo)致兩個引用指向同一個堆內(nèi)存中的java對象,通過任何一個引用去訪問堆內(nèi)存當(dāng)中的對象,此對象內(nèi)存都會受到影響。我們來驗證一下,讓a++,a應(yīng)該變成了11,但是b不會變,讓bird1.name = “波利”,然后輸出bird2.name的結(jié)果肯定也是”波利”,請看代碼以及運(yùn)行結(jié)果:
public class AssignmentTest {
public static void main(String[] args) {
//基本數(shù)據(jù)類型
int a = 10;
int b = a; //a賦值給b,a把什么給了b?
a++;
System.out.println("a = " + a);
System.out.println("b = " + b);
//引用數(shù)據(jù)類型
Bird bird1 = new Bird("polly");
//bird1賦值給bird2,bird1把什么給了bird2?
Bird bird2 = bird1;
System.out.println("bird1's name = " + bird1.name);
System.out.println("bird2's name = " + bird2.name);
bird1.name = "波利";
System.out.println("bird1's name = " + bird1.name);
System.out.println("bird2's name = " + bird2.name);
}
}
class Bird {
String name;
public Bird(){}
public Bird(String _name){
name = _name;
}
}
運(yùn)行結(jié)果如下圖所示:
圖9-34:賦值原理測試
上面我就提到了,方法調(diào)用時參數(shù)的傳遞和賦值運(yùn)算符的原理完全相同,那么請大家根據(jù)以上內(nèi)容所學(xué),畫出以下程序的內(nèi)存圖,以及推算它們的執(zhí)行結(jié)果:
public class ParameterTransferTest01 {
public static void main(String[] args) {
int i = 10;
add(i);
System.out.println("main's i = " + i);
}
public static void add(int i){
i++;
System.out.println("add's i = " + i);
}
}
public class ParameterTransferTest02 {
public static void main(String[] args) {
User user = new User(20);
add(user);
System.out.println("main's user age = " + user.age);
}
public static void add(User user) {
user.age++;
System.out.println("add's user age = " + user.age);
}
}
class User{
int age;
public User(){}
public User(int _age){
age = _age;
}
}