java中按值傳遞和按引用傳遞問題

來源:互聯網
上載者:User

標籤:java   按值傳遞   按引用傳遞   

  相信對很多初學java的人來說這個問題還是很重要,因為不同於C,C++,java明確說明取消了指標,因為指標往往是再帶來方便的同時也是導致代碼不安全的根源,而且還會使得程式變得非常複雜和難以理解。java放棄指標只是在java語言中沒有明確的指標定義,實質上,每一個new語句返回的都是一個指標的引用。只不過在大多數時候java不用關心如何操作這個“指標”,更不像在操作C++的指標那樣膽戰心驚,唯一要多注意的是在給函數傳遞對象的時候。所以,初學java的人不必花費太多精力去瞭解,但是對於一個真正的java程式員來說這個問題是基礎。廢話少說,直接進入正題:

    java中是傳值還是傳引用呢 ?  

 關於這個問題,就像光到底是波還是粒子的問題一樣眾說紛紜。但是我們首先要搞清楚一點:不管java的參數類型是什麼,一律傳遞參數的副本(引用thinking in Java 中的一句話:When you‘re passing primitives into a method, you get a distinct copy of the primitive.When you‘re passing a reference into a method, you get a copy of the reference)。

java中的變數分為以下兩類:

(1)基本類型變數(int,long,double,boolean,float, byte,char),對於這些變數,java傳遞的是值的副本(與c++相同),即把自己賦值一份傳遞,即使自己的副本變了,自己也不會改變;

(2)對象型變數。java傳遞的是引用的副本(複製指向地址的指標),而不是自己實際值的副本。為啥這麼做呢?原因很簡單,因為物件類型是放在堆裡邊的(new一個對象的時候實際上是再堆中開闢出了一塊記憶體空間存放對象,在棧中存放指向對象的指標),所以訪問位於堆中的對象相對於基本類型資料來說比較慢;另一方面是因為物件類型本身就比較大,如果採用複製對象值的方法,不僅浪費記憶體而且速度比較慢。

在thinking in Java 中解釋是這樣的:不管是基本類型還是物件類型,都是傳值。這種說法是把引用的副本也看作了一種“值”,也能夠說的過去,但是本人還是更贊成將按值傳遞和按引用傳遞分開比較好理解。

注意:java中String類型也是對象型變數,所以它傳遞的是引用的副本。String是一個非可變類,其傳值還是傳引用顯得沒什麼區別。


理論說完了,下面看幾個例子:

num1:傳基本類型

 

public class Test {

public static void test(boolean test) {

test = !test;

System.out.println("In test(boolean):test = " + test);

}

public static void main(String args[]) {

boolean test = true;

System.out.println("Before test(boolean):test = " + test);

test(test);

System.out.println("After test(boolean):test = " + test);

}


}


運行結果:  

Before test(boolean):test = true

In test(boolean):test = false   //傳進去的是boolean類型的副本,副本改變了但是原值不改變

After test(boolean):test = true

num2:傳物件類型

public class Test {

public static void test(StringBuffer str) {

str.append(", World!");

}

public static void main(String args[]) {

StringBuffer string = new StringBuffer("Hello");

test(string);

System.out.println(string);

}


}


運行結果:Hello, World!   //通過引用副本找到地址,然後修改裡邊的值,即修改了對象。

num3:關於傳String

public class Test {

public static void test(String str) {

str = "World";

}

public static void main(String args[]) {

String string = "Hello";

test(string);

System.out.println(string);

}


}

一眼看去輸出結果應該是:World

但是實際的運行結果卻是:Hello,String不是按引用傳遞的嗎?難道出問題了?

查了一下,原因如下:

  執行str = “World”;這句的時候,系統會自動產生一個新的String對象,並把這個新對象的值設為“World”,然後將這個對像的引用賦值給str,str是原來String的副本,改變的是副本的值,那麼就與原來的值沒有關係了。當test函數執行完畢,str隨之釋放,原來的記憶體位址上內容沒發生任何變化。因此輸出hello,num2中str.append(", World!");就不一樣了,StringBuffer是產生一塊記憶體空間,相關的增、刪、改操作都在其中進行,所以此句是在同一段記憶體上進行的,即修改了原值,str所指向的引用並沒有變。

  水平有限,希望各位大神給予指正補充,Thank you!

本文出自 “開發交流,共同進步” 部落格,請務必保留此出處http://smile2015.blog.51cto.com/9250194/1629685

java中按值傳遞和按引用傳遞問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.