這是一個Java的經典問題,大部分人從C,C++語言入門,C語言有三種傳遞方式:值傳遞,地址傳遞和引用傳遞。詳細的對C語言指針,引用的我個人的理解,見鏈接。
Java所有操作都是傳值操作!都是傳值操作!都是傳值操作!重要的事情說三遍。
疑問?那為什么別人講的時候都是說,java的基本數據類型都是傳值,所有的自定義數據(類的對象)都是傳引用??
很簡單,因為這樣好理解,意思是說:“同學們,如果我們把一個基本數據類型的值(變量)傳遞給一個函數的形參,那么無論我們對這個變量怎么操作,函數運行完之后,並不會改變這個變量的值!(到這里都是對的)但是如果我們把一個類的實例(對象)作為參數傳遞給函數,那么我們在函數里面對這個對象的改變,會實際地改變這個對象的值!(這里就不完全正確了)”。
對於Java的對象與引用的理解,請參見:淺談Java中的對象和引用。我這里簡單說一下Person person = new Person("張三"),這里面new Person("張三")是類Person的實例(或者說是對象),person是這個實例(對象)的引用。
Java的參數傳遞都是值傳遞!!!
先貼一篇博文:理解Java中的引用傳遞和值傳遞,如果你覺得這個人講的很有道理,那么你是麻瓜(哇!馬老師附體!)。我先不解釋,去看下這篇博文的1樓評論!
我們先定義,什么是值傳遞,什么是引用傳遞。
值傳遞:方法調用時,實際參數把它的值的副本傳遞給對應的形式參數。特點:此時內存中存在兩個相等的基本類型,即實際參數和形式參數,后面方法中的操作都是對形參這個值的修改,不影響實際參數的值。
引用傳遞:方法調用時,實際參數的引用(地址,而不是參數的值)被傳遞給方法中相對應的形式參數,函數接收的是原始值的內存地址;特點:在方法執行中,形參和實參內容相同,指向同一塊內存地址,方法執行中對引用的操作將會影響到實際對象。
值傳遞實在是太簡單了,大家應該都容易理解,既然傳遞的是實際參數的副本,那么更改這個副本,跟原來的變量沒有一點關系。
但是對於引用傳遞,一般的支持引用的例子我也不說了。看一個稍微特殊的例子:如果我們把下面的例子理解為引用傳遞,輸出應該是: LI Si 才對!因為zhangsan這個(new Person("ZHANG San")的)引用指向了新的對象!但實際結果是zhangsan這個引用指向的對象的名字並沒有變!
1 public class ValueOrRef { 2 public static void main(String[] args) { 3 Person zhangsan = new Person("ZHANG San"); 4 changePerson(zhangsan); 5 zhangsan.printName(); 6 } 7 public static void changePerson(Person person){ 8 person = new Person("LI Si"); 9 } 10 } 11 12 class Person { 13 String name = "default"; 14 public Person(String name) { 15 this.name = name; 16 } 17 public void changeName(String name){ 18 this.name = name; 19 } 20 void printName() { 21 System.out.println(this.name); 22 } 23 }
所以這里,我們把這種傳遞也理解為”值傳遞“只不過這里的值,是一個”引用”的值!也就是我們把實際參數(一個引用)拷貝一份賦值給形式參數,形式參數進行操作。當形式參數對本身的對象進行了變動操作,這里的效果跟引用傳遞是相同的。但是一旦給形式參數進行賦值類型的操作,這個賦值操作並不會像C語言的引用那樣,把這個賦值的效果反映在函數運行結束之后!!
總結:不要糾結與值傳遞與引用傳遞的概念了,我們明白函數執行的過程就好了!為了更好地理解整個運行過程的變化,請參考:Java:按值傳遞還是按引用傳遞詳細解說(其中有圖片演示,很清楚)。
