作者adrianshum (Alien)
看板java
標題Re: [問題] 新手程式流程問題
時間Sat May 25 23:54:38 2013
※ 引述《tzk28419 (甲鳥)》之銘言:
: 麻煩各位了
: 今天腦子打結
: 有關這個程式的輸出值
: public class Student{
: public int id;
: }
: public static void change(Student x){
: x.id=102;
: }
: public static void main (String[] args){
: Student s1=new Student();
: s1.id=101;
: change(s1);
: System.out.println(s1.id);
: }
: 如果Java中全部都是call by value來看的話
: 印出的結果應該是101才對
: 可是為什麼答案是102呢?
: 而且在x.id=102;前面多加x=new Student();就會和我起先想的一樣是101
: 這兩者我以後要如何分別呢?
: 流程是怎樣跑的?
看在推文中也有站友說不明白,我嘗試解釋一下。
首先,Java只有 pass-by-value (在這版戰過很多
次了,這說法連 JLS 自己也是這樣說,我不希望又
執著這個話題又有戰火了)
首先為免詞語混淆,我先把一個 Java 裡常用的字改
一改名。Java 裡常說到非 primitive type 的 var
就是 reference type。在這篇中我把這個名詞改為
Pointer (有 C/C++ 經驗的,就把它常成 C/C++ 裡
的 pointer 吧)。因為這個 "reference" 和 "pass
by reference" 放在一起經常讓人眼花。
常說 Java 只有 Pass-by-value,而原 po 例子中,
Student 明明沒有 pass-by-value,為什麼?
首先要記著,一個非 primitive 的 var, 它就是 pointer。
即是,
Student s1=new Student();
裡面,s1 本身不是一個 Student 的 Object, 它是
Student 的 Pointer, 它只是指向一個 Student 的
Object 而已。
明白了這,一切都好解說了。
change(s1) 的確是 pass-by-value。可是要記著,傳進
change() 的,不是一個 Student 的 Object,而是一個
Student 的 pointer,所以,被拷貝了一份的,是 pointer
而非 student 的 object. 用圖解說一下吧:
你的第一個情況
Student s1 = new Student()
+------------+
s1 [0x12345678] ------------> | Student |
| - id: 0 |
+------------+
Student s1 = new Student()
s1.id = 101;
+------------+
s1 [0x12345678] ------------> | Student |
| - id:
101 |
+------------+
Student s1 = new Student()
s1.id = 101;
change(s1)
change(x) {
+------------+
s1 [0x12345678] ------------> | Student |
+-> | - id: 101 |
| +------------+
|
x [0x12345678] ------------+
Student s1 = new Student()
s1.id = 101;
change(s1)
change(Student x) {
x.id = 102;
+------------+
s1 [0x12345678] ------------> | Student |
+-> | - id:
102 |
| +------------+
|
x [0x12345678] ------------+
Student s1 = new Student()
s1.id = 101;
change(s1)
change(Student x) {
x.id = 102;
}
s.id
+------------+
s1 [0x12345678] ------------> | Student |
+-> | - id:
102 |
| +------------+
|
x [0x12345678] ------------+
完結後, s1.id 當然拿到 102.
好了,第二個情況,你加了 x = new Student(),到這步為
止和第一情況都一樣:
Student s1 = new Student()
s1.id = 101;
change(s1)
change(Student x) {
+------------+
s1 [0x12345678] ------------> | Student |
+-> | - id: 101 |
| +------------+
|
x [0x12345678] ------------+
Student s1 = new Student()
s1.id = 101;
change(s1)
change(Student x) {
x = new Student();
+------------+
s1 [0x12345678] ------------> | Student |
| - id: 101 |
+------------+
+------------+
x [0x98765432] -------------> | Student |
| - id : 0 |
+------------+
Student s1 = new Student()
s1.id = 101;
change(s1)
change(Student x) {
x = new Student();
x.id = 102;
}
+------------+
s1 [0x12345678] ------------> | Student |
| - id: 101 |
+------------+
+------------+
x [0x98765432] -------------> | Student |
| - id :
102 |
+------------+
change 完結後,s1 當然還是拿到 101
應該清楚了吧?
Alien
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 223.19.42.175
※ 編輯: adrianshum 來自: 223.19.42.175 (05/25 23:57)
推 swpoker:只能推了 05/25 23:58
推 wannawanna:推圖解說明 05/26 00:38
推 andymai:其實講到pointer pass by value就該懂了~大大還用心畫了圖 05/26 07:26
推 tzk28419:我懂了!!謝謝Alien!!超棒的圖!!!! 05/26 08:44
推 kaocoming:推推!!!!! 05/26 09:34
推 Expsun:用心給推! 05/26 10:05
推 tails32100:推用心畫>< 05/26 10:10
推 aiueoH:推~ 05/26 13:15
→ aiueoH:不知道可否順便問一下 C# 是不是也是如此? 05/26 13:19
推 fonz:畫圖畫的很用心XD~ 大推 05/26 15:34
推 hotscott:推推!! 清楚~ 05/26 18:20
推 KanoLoa:這類問題都會讓我慶幸以前C有學過point 05/26 19:46
推 a88258850:感謝~ 05/26 22:06
推 nhtyjm:用心推 05/27 00:16
→ adrianshum:KanoLoa: 是 pointer, 不是 point 05/27 06:55
→ adrianshum:aiueoH: 只看過 C# 的皮毛,C# 不是以 primitive/ref 05/27 06:56
→ adrianshum:作分野,而是根據忘了什麼規定去決定傳的是 pointer 05/27 06:57
→ adrianshum:還是obj 本身。不過只要傳的是 pointer, 概念也一樣 05/27 06:57
推 KanoLoa:XD 05/27 08:40
推 abola921:推! 少見的圖解法 05/27 10:17
推 aiueoH:謝謝 adrianshum ~ 瞭解 05/27 10:49
推 gmoz:清楚明白 05/27 12:41
推 PsMonkey:樓上讓我想到《奪命金》 XD 05/27 12:57
推 brianhsu:推圖解~ 05/27 14:47
推 coolcomm:推 05/27 20:45
→ swpoker:其實這個在j2se的官方教學書冊裡面就有了 05/28 13:36
推 lsunyu:疑 第10頁上面第一個位置為什麼id拿到了102? 05/28 22:35
推 issuemylove:pass-by-value 05/29 16:10
推 lsunyu:可是第10頁不是還在x = new Student(); 階段 id=102? 05/30 00:46
→ adrianshum:樓上:明顯是筆誤:P 改正中 06/01 22:43
※ 編輯: adrianshum 來自: 223.19.42.175 (06/01 22:45)
推 cn1754:推 06/02 23:28
推 qskyq0013:推推~ 06/11 20:25
推 silentduke:好文 專業圖解 06/11 23:53
推 moonjuice:謝謝解惑。很清楚!! 06/22 01:35
推 kspacey:推 06/22 20:48