1. 程式人生 > >append進StringBuilder裡的字串是""還是"null"? Java

append進StringBuilder裡的字串是""還是"null"? Java

有這樣一個需求:有一個類,它有幾個域,希望它的toString方法返回它的所有域的值組合成的字串,域值之間用某種分隔符(比如####)分隔。我是這樣實現的:

public class CombineFieldWithDelimiter {
    private String field1;
    private String field2;
    private String field3;

    public CombineFieldWithDelimiter() {
    }

    @Override
    public String toString() {
        String delimiter ="####"
; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(delimiter); stringBuilder.append(field1); stringBuilder.append(delimiter); stringBuilder.append(field2); stringBuilder.append(delimiter); stringBuilder.append(field3); return
stringBuilder.toString(); } public void setField1(String field1) { this.field1 = field1; } public void setField2(String field2) { this.field2 = field2; } public void setField3(String field3) { this.field3 = field3; } public static void main
(String[] args) { CombineFieldWithDelimiter combineFieldWithDelimiter = new CombineFieldWithDelimiter(); System.out.println(combineFieldWithDelimiter.toString()); } }

當執行這個類的時候,我希望的輸出是:

########

而實際上是:

null####null####null

為什麼實際的輸出和期望的不一樣呢?看看StringBuilder的append(String)方法的原始碼:

    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

繼續檢視它父類的append(String)方法的原始碼:

    public AbstractStringBuilder append(String str) {
        // null字串當做"null"處理
        if (str == null) str = "null";
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

原來如此,當字串為null時,就被當做”null”處理。因為我知道,如果沒有顯式的給CombineFieldWithDelimiter 類的各個域賦值,它們都將是null,所以,問題就明瞭了。為了解決問題,我只需顯式的給每個域賦字串”“就可以了,像下面這樣:

public class CombineFieldWithDelimiter {
    private String field1 = "";
    ...
}

如果同學們對虛擬機器中物件的建立過程不太瞭解,這裡簡單介紹一下。當我們new一個物件時,虛擬機器首先去檢查要建立物件的類是否已經載入(包括載入、連線和初始化)了,如果沒有,就執行相應的類載入過程;然後虛擬機器就給物件分配記憶體並把分配的記憶體空間都初始化為零值,給記憶體空間賦零值得操作使得物件的例項欄位可以在不賦初始值的情況下也能直接使用,但都是相應的零值,對於物件域來說,就是null,理解了這一點,才算是真正理解本文了;最後是執行物件初始化方法<init>,給物件的域賦上程式設計師指定的值,例如,在我對上CombineFieldWithDelimiter的代買進行修改後,下面的語句執行後,

CombineFieldWithDelimiter combineFieldWithDelimiter = new CombineFieldWithDelimiter();

field1的值不是null,而是“”了。當執行完成後,一個真正可用的物件才算完全產生出來。