java值傳遞徹底明白~

來源:互聯網
上載者:User
時間: 2004-4-06 13:18:27    標題: 一個絕對害了不少人的Java技術問題!
我不記得自己是怎麼學到的,但是我相信絕大部分從事java學習Java的人都一直這麼以為一個小的技術問題:
在Java中方法參數的傳遞,對象是傳遞引用,基礎資料型別 (Elementary Data Type)是傳遞值。而且一直一來都似乎沒有人提出過疑問。
直到最近,我在為公司基本Java開發人員編寫考試試卷的時候,我才發現,這錯了!在方法中,Java語言中對象傳遞的是地址,而不是引用,這兩個概念是有非常大的差別的,我相信熟悉c++的人都應該知道。
例如下面:假設對象Test有name的屬性。
public void call(Test t) {
Test t2 = new Test();
t2.setName("cba');
t.setName("abc");
t = t2 ;
}

public static void main(String[] arg) {
Test obj = new Test();
call (obj) ;
System.out.println("obj"+obj.getName());
}
這個時候,你們可以發現,列印出來的是"abc" ,而不是"cba",原因是這樣的,在這次調用中,等於聲明了兩個變數obj , t,它們指向的是同一個地址,調用call方法,只是將obj指向的地址傳遞給了t,而obj本身並沒有傳遞過去(也就是沒有傳遞引用),當你重新賦值的時候(也就是將對象引用指向其他儲存空間),等於隻影響了t,而沒有影響obj。
這樣的傳遞方式只能稱之為址傳遞,或者是引用對象傳遞,而不嫩說是傳遞引用或者引用傳遞。
我不知道這究竟屬於翻譯的錯誤,還是我們理解的錯誤。但是這樣的問題在c++中是有明顯的區分的(通過*與&)

時間: 2004-4-06 21:07:10    標題:
1、首先弄清楚一個問題:Java有沒有指標?

對於在C和C++裡頭曾經給我們帶來歡樂同時也有無限痛苦的指標,很多人寧願它再也不要出現在Java裡頭。然而事實上,Java是有指標的,Java中每個對象(除基礎資料型別 (Elementary Data Type)以外)的標識符都屬於指標的一種。但它們的使用受到了嚴格的限制和防範,在<Thinking in Java>一書中稱它們為控制代碼。

2、傳遞控制代碼
將控制代碼傳遞進入一個方法時,指向的仍然是相同的對象。
public class Testit {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public static void main(String[] args) {
Testit a = new Testit();
a.setName("a");
Testit b = new Testit();
b.setName("b");
System.out.println("before swap: " + "a=" + a + " name: " + a.getName());
swap(a,b);
}

private static void swap(Testit swap1, Testit swap2) {
System.out.println("swaping: " + "a= " + swap1 + " name: " + swap1.getName());
Testit temp;
temp = swap1;
swap1 = swap2;
swap2 = temp;
}

}

輸出結果:
before swap: a=com.lib.Testit@16930e2 name: a
swaping: a= com.lib.Testit@16930e2 name: a

3、一個控制代碼的傳遞會使調用者的對象發生意外的改變。
public class Testit {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public static void main(String[] args) {
Testit a = new Testit();
a.setName("a");
Testit b = new Testit();
b.setName("b");
System.out.println("before swap: " + "a=" + a + " name: " + a.getName());
swap(a,b);
System.out.println("after swap: " + "a=" + a + " name: " + a.getName());
}

private static void swap(Testit swap1, Testit swap2) {
Testit temp;
temp = swap1;
swap1 = swap2;
swap2 = temp;
swap1.setName("a's name");
swap2.setName("b's name");
}

}

輸出結果:
before swap: a=com.lib.Testit@16930e2 name: a
after swap: a=com.lib.Testit@16930e2 name: b's name

我們看到,a依舊是原來那個a,但name卻不是原來那個name了!
在swap()方法中,swap1和swap2互相換過來了,這個時候swap2指向的是a,所以在setName()的時候改變的是a的name,而不是b的name。

為什麼會這樣呢?
liang_chen兄高見:Java裡的傳值實際上是拷貝引用,而不是拷貝對象。

總結:
1:對於實值型別的參數來說,傳遞的是值的拷貝.
2:對於參考型別的參數來說,傳遞的是引用本身的拷貝.
所以關鍵要看你如何理解傳值中的這個“值”了。

時間: 2004-4-06 22:56:27    標題: 哈哈,好熱鬧
沒有想到這個問題引起這麼多朋友的共鳴,
樓上有位仁兄關於“java傳遞是引用的拷貝,既不是引用本身,更不是對象。”這句話說得非常好!可惜現今發現的任何一本書都沒有說明。
當然這個傳遞是對象,而不是單一資料型別,單一資料型別還是傳遞值的拷貝的。
樓上還有一位仁兄拿出了編譯原理,這正是問題的所在,傳遞地址、傳遞引用、傳遞結果(也就是值拷貝),這裡所說的傳遞引用和傳遞地址有什麼差別?
樓上的liang_chen的理解非常好,我直到前一段才真正發現(在我身邊差不多都不清楚這個問題),三年多的java分析設計開發經驗,到今天才理解透這樣一個基礎的問題,我真是汗顏。:(
所以,其他還在爭論不清楚的各位朋友,一定要認真地學習java,不能隨便說自己精通的,哈哈,大家多加探討,繼續共同提高。

時間: 2004-11-10 12:38:00    標題: 控制代碼與指標--討論鳳舞凰揚的問題
鳳舞凰揚的原文章實在太長了,在這裡新開一個文章討論這個問題。

我認為,java並沒有c++中指標、地址的概念,它只有控制代碼(handler)的概念。還以鳳舞凰揚的兩個方法為例:

public void call(Test t) {
Test t2 = new Test();
t2.setName("cba');
t.setName("abc");
t = t2 ;
}

public static void main(String[] arg) {
Test obj = new Test();
call (obj) ;
System.out.println("obj"+obj.getName());
}

總共構建了兩個Test對象,假設稱main方法構建的對象為“對象1”,call方法構建的對象為“對象2”,
在main方法中,變數obj獲得了“對象1”的控制代碼,
在參數傳遞中,變數obj把這個控制代碼傳遞給變數t,
在call方法中,變數t首先改變了“對象1”的屬性,然後變數t又獲得了“對象2”的控制代碼(但obj仍然是“對象1”的控制代碼),
call方法返回後,由於“對象2”失去了唯一的控制代碼,不可避免的進入垃圾收集器的視線。而obj仍然是“對象1”的控制代碼,由於“對象1”的屬性已經被重新設定,所以我們可以看到列印出來的結果是“abc”。

所以我認為以下論斷是沒有問題的:
“在Java中方法參數的傳遞,對象是傳遞引用,基礎資料型別 (Elementary Data Type)是傳遞值。”

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.