先給出兩個(gè)例子引出今天所要討論的問題:
1
2 public class Person
3 {
4 private String name = null;
5 private int age = 0;
6
7 public Person(String name, int age) {
8 this.name = name;
9 this.age = age;
10 }
11
12 public void changeName(String newName) {
13 this.name = newName;
14 }
15
16 public void changeAge(int newAge) {
17 this.age = newAge;
18 }
19
20 public String toString() {
21 return "Person - Name: " + name + ", Age: " + age;
22 }
23 }
24
25 public class PassByValue
26 {
27 public static void main(String[] args) {
28 // one example
29 String value1 = "value1: aaa";
30 String value2 = "value2: bbb";
31
32 swapValue(value1, value2);
33
34 System.out.println(value1);
35 System.out.println(value2);
36
37 // another example
38 Person person = new Person("張三", 20);
39
40 System.out.println(person.toString());
41
42 changePerson(person);
43
44 System.out.println(person.toString());
45 }
46
47 public static void swapValue(String tmpValue1, String tmpValue2) {
48 String tempStr = tmpValue1;
49 tmpValue1 = tmpValue2;
50 tmpValue2 = tempStr;
51 }
52
53 public static void changePerson(Person tmpPerson) {
54 tmpPerson.changeName("李四");
55 tmpPerson.changeAge(30);
56 }
57 }
58
考慮一下上面這段代碼的輸出結(jié)果是什么?
我相信絕大多數(shù)人都能快速的給出正確答案:
value1: aaa
value2: bbb
Person - Name: 張三, Age: 20
Person - Name: 李四, Age: 30
答案為什么是這樣的呢?那么 Java 到底是按值傳遞還是按引用傳遞參數(shù)的呢?
例子1中的 swapValue() 方法不起作用,看起來是按值傳遞參數(shù)的,例子2中的 changeName() 和 changeAge() 方法起作用,從表面上看起來好像又是按引用傳遞參數(shù)的。呵呵,別急,先讓我們來弄清楚一個(gè)重要的概念,就是 Java 操縱對象都是通過引用來實(shí)現(xiàn)的,所有的對象變量都是所指向的對象的引用,那也就是說所有對象變量的值并不是它所指向的對象本身,而是該對象的引用,這句話聽起來可能有點(diǎn)讓人犯暈,舉個(gè)例子來說,String str = new String("aaa"); 這條語句的意思是 new 了一個(gè)值為 "aaa" 的字符串對象,然后用一個(gè)名字叫 str 的對象變量來指向它,保存它的引用,假設(shè)在內(nèi)存中 new 出來的這個(gè)字符串對象的實(shí)際地址為 0xA242, 那么 str 的值實(shí)際上是 0xA242。
現(xiàn)在來看看例子1,假設(shè)
String value1 = "value1: aaa" 的地址為 0xA242,
String value2 = "value2: bbb" 的地址為 0xA24B,
然我們來看看 swapValue(value1, value2); 語句 Java 是怎么執(zhí)行的。當(dāng)程序執(zhí)行到這句語句的時(shí)候,JVM 在棧中創(chuàng)建兩個(gè)臨時(shí)變量 tmpValue1,tmpValue2,用來接收傳進(jìn)來的 value1 和 value2 的值,而 value1 和 value2 的值分別為 0xA242 和 0xA24B,所以那兩個(gè)臨時(shí)變量 tmpValue1和tmpValue2 的值也被賦值為 0xA242 和 0xA24B,此時(shí)接下來的三條語句分別是
tempStr = 0xA242,
tmpValue1 = 0xA24B,
tmpValue2 = 0xA242;
此時(shí) tmpValue1 的值是指向 "value2: bbb" 這個(gè)對象的,
tmpValue2 的值是指向 "value1: aaa" 這個(gè)對象,你可以在 swapValue() 方法內(nèi)部打印 tmpValue1 和 tmpValue2 的值驗(yàn)證一下。
不過這里的 tmpValue1和tmpValue2 是在棧中的臨時(shí)變量,而并不是 main 方法中 value1和value2,main 方法中 value1和value2 的值并沒有改變,那這里所謂的值傳遞是指什么呢?因?yàn)?value1 的值是 0xA242("value1: aaa" 這個(gè)對象的引用),而并不是 "value1: aaa" 這個(gè)對象,傳遞參數(shù)時(shí)傳遞的是 "value1: aaa" 這個(gè)對象的引用也就是 value1 的值,所以是值傳遞。
例子2也是一樣的,假設(shè)
Person person = new Person("張三", 20) 的地址為 0xA242,
那么 person 的值是 0xA242, 那么通過調(diào)用 changePerson(person); 將 0xA242 傳遞給 tmpPerson, 也就是 tmpPerson 此時(shí)的值為 0xA242 也就是 new Person("張三", 20) 這個(gè)對象的引用,也就是說 tmpPerson 指向 new Person("張三", 20) 對象,對 tmpPerson 引用對象的修改實(shí)際上就是對 person 引用對象的修改,這看起來很想引用傳遞的概念,但實(shí)際上是值傳遞,為什么呢?因?yàn)樵趨?shù)傳遞過程中傳遞的是 person 的值,也就是 0xA242。
呵呵,好好體會(huì)吧。
歡迎來信指正錯(cuò)誤。
http://www.tkk7.com/qujinlong123/