亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

JAVA面試題解惑系列(五)——傳了值還是傳了引

系統 2355 0

好東西分享

JAVA中的傳遞都是值傳遞嗎?有沒有引用傳遞呢?

在回答這兩個問題前,讓我們首先來看一段代碼:

Java代碼 復制代碼
  1. public ? class ?ParamTest?{ ??
  2. ???? //?初始值為0 ??
  3. ???? protected ? int ?num?=? 0 ; ??
  4. ??
  5. ???? //?為方法參數重新賦值 ??
  6. ???? public ? void ?change( int ?i)?{ ??
  7. ????????i?=? 5 ; ??
  8. ????} ??
  9. ??
  10. ???? //?為方法參數重新賦值 ??
  11. ???? public ? void ?change(ParamTest?t)?{ ??
  12. ????????ParamTest?tmp?=? new ?ParamTest(); ??
  13. ????????tmp.num?=? 9 ; ??
  14. ????????t?=?tmp; ??
  15. ????} ??
  16. ??
  17. ???? //?改變方法參數的值 ??
  18. ???? public ? void ?add( int ?i)?{ ??
  19. ????????i?+=? 10 ; ??
  20. ????} ??
  21. ??
  22. ???? //?改變方法參數屬性的值 ??
  23. ???? public ? void ?add(ParamTest?pt)?{ ??
  24. ????????pt.num?+=? 20 ; ??
  25. ????} ??
  26. ??
  27. ???? public ? static ? void ?main(String[]?args)?{ ??
  28. ????????ParamTest?t?=? new ?ParamTest(); ??
  29. ??
  30. ????????System.out.println( "參數--基本類型" ); ??
  31. ????????System.out.println( "原有的值:" ?+?t.num); ??
  32. ???????? //?為基本類型參數重新賦值 ??
  33. ????????t.change(t.num); ??
  34. ????????System.out.println( "賦值之后:" ?+?t.num); ??
  35. ???????? //?為引用型參數重新賦值 ??
  36. ????????t.change(t); ??
  37. ????????System.out.println( "運算之后:" ?+?t.num); ??
  38. ??
  39. ????????System.out.println(); ??
  40. ??
  41. ????????t?=? new ?ParamTest(); ??
  42. ????????System.out.println( "參數--引用類型" ); ??
  43. ????????System.out.println( "原有的值:" ?+?t.num); ??
  44. ???????? //?改變基本類型參數的值 ??
  45. ????????t.add(t.num); ??
  46. ????????System.out.println( "賦引用后:" ?+?t.num); ??
  47. ???????? //?改變引用類型參數所指向對象的屬性值 ??
  48. ????????t.add(t); ??
  49. ????????System.out.println( "改屬性后:" ?+?t.num); ??
  50. ????} ??
  51. }??
    public class ParamTest {
	// 初始值為0
	protected int num = 0;

	// 為方法參數重新賦值
	public void change(int i) {
		i = 5;
	}

	// 為方法參數重新賦值
	public void change(ParamTest t) {
		ParamTest tmp = new ParamTest();
		tmp.num = 9;
		t = tmp;
	}

	// 改變方法參數的值
	public void add(int i) {
		i += 10;
	}

	// 改變方法參數屬性的值
	public void add(ParamTest pt) {
		pt.num += 20;
	}

	public static void main(String[] args) {
		ParamTest t = new ParamTest();

		System.out.println("參數--基本類型");
		System.out.println("原有的值:" + t.num);
		// 為基本類型參數重新賦值
		t.change(t.num);
		System.out.println("賦值之后:" + t.num);
		// 為引用型參數重新賦值
		t.change(t);
		System.out.println("運算之后:" + t.num);

		System.out.println();

		t = new ParamTest();
		System.out.println("參數--引用類型");
		System.out.println("原有的值:" + t.num);
		// 改變基本類型參數的值
		t.add(t.num);
		System.out.println("賦引用后:" + t.num);
		// 改變引用類型參數所指向對象的屬性值
		t.add(t);
		System.out.println("改屬性后:" + t.num);
	}
}

  


這段代碼的運行結果如下:

  1. 參數--基本類型
  2. 原有的值:0
  3. 賦值之后:0
  4. 運算之后:0
  5. 參數--引用類型
  6. 原有的值:0
  7. 賦引用后:0
  8. 改屬性后:20


從上面這個直觀的結果中我們很容易得出如下結論:

  1. 對于基本類型,在方法體內對方法參數進行重新賦值,并不會改變原有變量的值。
  2. 對于引用類型,在方法體內對方法參數進行重新賦予引用,并不會改變原有變量所持有的引用。
  3. 方法體內對參數進行運算,不影響原有變量的值。
  4. 方法體內對參數所指向對象的屬性進行運算,將改變原有變量所指向對象的屬性值。


上面總結出來的不過是我們所看到的表面現象。那么,為什么會出現這樣的現象呢?這就要說到值傳遞和引用傳遞的概念了。這個問題向來是頗有爭議的。

大家都知道,在JAVA中變量有以下兩種:

  1. 基本類型變量,包括char、byte、short、int、long、float、double、boolean。
  2. 引用類型變量,包括類、接口、數組(基本類型數組和對象數組)。


當基本類型的變量被當作參數傳遞給方法時,JAVA虛擬機所做的工作是把這個值拷貝了一份,然后把拷貝后的值傳遞到了方法的內部。因此在上面的例子中,我們回頭來看看這個方法:

Java代碼 復制代碼
  1. //?為方法參數重新賦值 ??
  2. public ? void ?change( int ?i)?{ ??
  3. ????i?=? 5 ; ??
  4. }??
    	// 為方法參數重新賦值
	public void change(int i) {
		i = 5;
	}

  


在這個方法被調用時,變量i和ParamTest型對象t的屬性num具有相同的值,卻是兩個不同變量。變量i是由JAVA虛擬機創建的作用域在change(int i)方法內的局部變量,在這個方法執行完畢后,它的生命周期就結束了。在JAVA虛擬機中,它們是以類似如下的方式存儲的:


很明顯,在基本類型被作為參數傳遞給方式時,是值傳遞,在整個過程中根本沒有牽扯到引用這個概念。這也是大家所公認的。對于布爾型變量當然也是如此,請看下面的例子:

Java代碼 復制代碼
  1. public ? class ?BooleanTest?{ ??
  2. ???? //?布爾型值 ??
  3. ???? boolean ?bool?=? true ; ??
  4. ??
  5. ???? //?為布爾型參數重新賦值 ??
  6. ???? public ? void ?change( boolean ?b)?{ ??
  7. ????????b?=? false ; ??
  8. ????} ??
  9. ??
  10. ???? //?對布爾型參數進行運算 ??
  11. ???? public ? void ?calculate( boolean ?b)?{ ??
  12. ????????b?=?b?&&? false ; ??
  13. ???????? //?為了方便對比,將運算結果輸出 ??
  14. ????????System.out.println( "b運算后的值:" ?+?b); ??
  15. ????} ??
  16. ??
  17. ???? public ? static ? void ?main(String[]?args)?{ ??
  18. ????????BooleanTest?t?=? new ?BooleanTest(); ??
  19. ??
  20. ????????System.out.println( "參數--布爾型" ); ??
  21. ????????System.out.println( "原有的值:" ?+?t.bool); ??
  22. ???????? //?為布爾型參數重新賦值 ??
  23. ????????t.change(t.bool); ??
  24. ????????System.out.println( "賦值之后:" ?+?t.bool); ??
  25. ??
  26. ???????? //?改變布爾型參數的值 ??
  27. ????????t.calculate(t.bool); ??
  28. ????????System.out.println( "運算之后:" ?+?t.bool); ??
  29. ????} ??
  30. }??
    public class BooleanTest {
	// 布爾型值
	boolean bool = true;

	// 為布爾型參數重新賦值
	public void change(boolean b) {
		b = false;
	}

	// 對布爾型參數進行運算
	public void calculate(boolean b) {
		b = b && false;
		// 為了方便對比,將運算結果輸出
		System.out.println("b運算后的值:" + b);
	}

	public static void main(String[] args) {
		BooleanTest t = new BooleanTest();

		System.out.println("參數--布爾型");
		System.out.println("原有的值:" + t.bool);
		// 為布爾型參數重新賦值
		t.change(t.bool);
		System.out.println("賦值之后:" + t.bool);

		// 改變布爾型參數的值
		t.calculate(t.bool);
		System.out.println("運算之后:" + t.bool);
	}
}

  


輸出結果如下:

  1. 參數--布爾型
  2. 原有的值:true
  3. 賦值之后:true
  4. b運算后的值:false
  5. 運算之后:true


那么當引用型變量被當作參數傳遞給方法時JAVA虛擬機又是怎樣處理的呢?同樣,它會拷貝一份這個變量所持有的引用,然后把它傳遞給JAVA虛擬機為方法創建的局部變量,從而這兩個變量指向了同一個對象。在篇首所舉的示例中,ParamTest類型變量t和局部變量pt在JAVA虛擬機中是以如下的方式存儲的:


有一種說法是當一個對象或引用類型變量被當作參數傳遞時,也是值傳遞,這個值就是對象的引用,因此JAVA中只有值傳遞,沒有引用傳遞。還有一種說法是引用可以看作是對象的別名,當對象被當作參數傳遞給方法時,傳遞的是對象的引用,因此是引用傳遞。這兩種觀點各有支持者,但是前一種觀點被絕大多數人所接受,其中有《Core Java》一書的作者,以及JAVA的創造者James Gosling,而《Thinking in Java》一書的作者Bruce Eckel則站在了中立的立場上。

我個人認為值傳遞中的值指的是基本類型的數值,即使對于布爾型,雖然它的表現形式為true和false,但是在棧中,它仍然是以數值形式保存的,即0表示false,其它數值表示true。而引用是我們用來操作對象的工具,它包含了對象在堆中保存地址的信息。即使在被作為參數傳遞給方法時,實際上傳遞的是它的拷貝,但那仍是引用。因此,用引用傳遞來區別與值傳遞,概念上更加清晰。

最后我們得出如下的結論:

  1. 基本類型和基本類型變量被當作參數傳遞給方法時,是值傳遞。在方法實體中,無法給原變量重新賦值,也無法改變它的值。
  2. 對象和引用型變量被當作參數傳遞給方法時,在方法實體中,無法給原變量重新賦值,但是可以改變它所指向對象的屬性。至于到底它是值傳遞還是引用傳遞,這并不重要,重要的是我們要清楚當一個引用被作為參數傳遞給一個方法時,在這個方法體內會發生什么。

向原作者致敬,轉自:

作者:臧圩人(zangweiren)
網址: http://zangweiren.iteye.com

JAVA面試題解惑系列(五)——傳了值還是傳了引用?


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产娱乐凹凸视觉盛宴在线视频 | 香蕉视频亚洲 | 夜精品a一区二区三区 | 国产成a人亚洲精v品久久网 | 亚洲精品久久久久久动漫剧情 | 中文字幕免费 | 性生活视频免费观看 | 国产精品青青青高清在线密亚 | 亚州综合 | 日本护士一级毛片在线播放 | 尹人香蕉网在线观看视频 | 羞羞视频在线观看 | 在线久操 | 五月天中文在线 | 爽爽影院免费观看视频 | 福利视频国产 | 免费观看一级欧美在线视频 | 亚洲色无码播放 | 久久99热这里只有精品国产 | 精品国产一区二区三区免费 | 激情婷婷成人亚洲综合 | 91精品中文字幕 | 亚洲人和日本人jzz护士 | 综合色综合 | 国产精品成人在线 | 中文字幕人成不卡一区 | 99视频在线播放 | 爱爱永久免费视频网站 | 国产亚洲精品一品区99热 | 一本久道久久综合狠狠爱 | 国产一区二区亚洲精品 | 日日操夜夜操视频 | 久久精品国产91久久麻豆自制 | 中文字幕不卡 | 天天综合天天射 | 国产在线精品观看一区 | 国产精品tv | 久青草国产手机视频免费观看 | 日韩久久免费视频 | 亚洲综合日韩 | 久久久国产精品免费 |