字符串是經過「引用」傳遞的

這是Java中一個很經典的問題,在stack-overflow上有不少相似的問題,然而不少回答都是錯的或者回答不完整;若是你不深刻思考的話,會認爲這個問題很簡單,可是當你深刻下去,會發現這個問題很容易讓人產生困惑。java

一段有趣且讓人困惑的代碼

package simplejava;

public class Q14 {

    public static void change(String x) {
        x = "cd";
    }

    public static void main(String[] args) {
        String x = new String("ab");
        change(x);
        System.out.println(x);
    }

}

結果打印:web

ab

C++版本以下:app

void change(string &x) {
    x = "cd";
}
int main(){
    string x = "ab";
    change(x);
    cout << x << endl;
}

打印結果:ui

cd

常見有誤的理解

x變量存儲了堆中「ab」對象的引用,當x做爲一個參數傳入到change()方法內部時,仍然指向堆中的「ab」對象,以下所示:spa

由於Java是按值傳遞的,x的值是「ab」對象的引用,當方法change()被調用時,建立了一個新的對象「cd」,而後x指向「cd」對象,以下圖所示:code

這看起來像是一個完美的解釋,他們很清楚Java老是按值傳遞的。可是,問題到底出在哪裏呢?對象

這段代碼到底究竟在作什麼

上面的解釋有若干處錯誤,爲了更加容易的理解該問題,咱們仍是先理清下整個過程。blog

當字符串對象「ab」被建立的時候,Java分配了對應大小的內存空間,而後對象被賦值給變量x,事實上是x變量存儲的是對象的引用,這個引用是「ab」對象在內存中的地址;內存

x變量包含了對象的引用,x並非「ab」對象,而是一個存儲了「ab」對象引用(內存地址)的變量。字符串

Java是按值傳遞的,當x被傳入change()方法的時候,事實上傳入的是一個x變量的拷貝。而後在方法change()內部建立了另外一個對象「cd」,它有一個不一樣的引用。真正改變的是這個x變量的拷貝,其值變成了「cd」對象的引用,而不是原始的x變量被改變;

注:感受說得有點混亂,個人理解,先說這個參數x,其至關於一個局部變量,當使用該參數的時候,將會分配一個新的存儲位置,將實參拷貝到該位置,並將該拷貝值傳遞給該方法;

在change()方法內部,執行x = "cd"的時候,這裏的x其實是main方法的x變量的一個拷貝,一開始其存放的是「ab對象」的引用,執行完這段代碼後,其值變成「cd」對象的引用,而main方法的x變量並無改變,存放的仍然是「ab」對象的引用。

另外一錯誤解釋

這個問題的緣由跟字符串的不變形沒任何關係,即便將String替換成StringBuilder對象,結果仍然不變,關鍵點是變量存儲的是對象的引用,而不是對象自己;

解決這個問題的方法

若是真的想改變這個對象的值,

首先這個對象是要可改變的,例如StringBuilder。

其次,咱們要保證沒有新對象被建立賦值給參數變量,由於Java只能按值傳遞。

以下代碼:

public static void main(String[] args) {
    StringBuilder x = new StringBuilder("ab");
    change(x);
    System.out.println(x);
}
public static void change(StringBuilder x) {
    x.delete(0, 2).append("cd");
}

 

譯文連接:http://www.programcreek.com/2013/09/string-is-passed-by-reference-in-java/

相關文章
相關標籤/搜索