2008-09-05 72 views
245

printf的得到了一種添加到Java與1.5版本,但我似乎無法找到如何將輸出發送到一個字符串,而不是一個文件(這是什麼做的sprintf在C)。有誰知道如何做到這一點?的sprintf相當於在Java中

回答

415
// Store the formatted string in 'result' 
String result = String.format("%4d", i * j); 

// Write the result to standard output 
System.out.println(result); 

format及其syntax

22

@erickson。

字符串是不可變的類型。你不能修改它們,只返回新的字符串實例。

正因爲如此,「富」 .format()沒有什麼意義,因爲它會被稱爲像

string newString = "foo".format(); 

原始的Java作者(和.NET的作者),決定一個靜態方法在這種情況下更有意義,因爲你沒有修改「foo」,而是調用一個格式化方法並傳入一個輸入字符串。

編輯:嘿,這個網站有時候可能會很有趣。我提到了字符串是不可變類型的事實。

下面是爲什麼格式()將啞作爲一個實例方法的實例。在.NET中(可能在Java中),Replace()是一種實例方法。

你可以這樣做:

"I Like Wine".Replace("Wine","Beer"); 

然而,什麼都不會發生,因爲字符串是不可改變的。替換嘗試返回一個新的字符串,但它被分配到什麼都沒有。

這會導致大量的普通新秀的錯誤,如:

// Contrived Example 
inputText.Replace(" ","%20"); 

再次,什麼也沒有發生,相反,你必須做的:

inputText = inputText.Replace(" ","%20"); 

現在,如果你明白字符串是不可變的,這使得完美的感覺。如果你不這樣做,那麼你只是感到困惑。用於替換的適當位置,將其中的格式,作爲字符串的靜態方法:

inputText = String.Replace(inputText," ", "%20"); 

現在有沒有問題,就是怎麼回事。

真正的問題是,爲什麼這些框架的作者決定一個人應該是一個實例方法,與其他靜態?在我看來,兩者都更加優雅地表達爲靜態方法,但是erickson似乎認爲兩者都屬於實例方法。

不管你的意見,但事實是,你是不容易使使用靜態版本一個錯誤,代碼更容易理解(無隱藏陷阱)。

當然也有一些方法是完美的,因爲實例方法,採取string.length減()

int length = "123".Length(); 

在這種情況下,其明顯的,我們是不是要修改「123」,我們只是檢查它,並返回它的長度......這是一個實例方法的完美候選人。

我的實例方法簡單的規則上不可變對象:

  • 如果需要返回相同類型的新實例,使用一個靜態方法。
  • 否則,請使用實例方法。
+3

我看到你以某種方式得到了我建議格式字符串被修改的想法。我從來沒有考慮過某個人可能會期望一個字符串改變的可能性,因爲他們的不變性是非常基本的。 – erickson 2008-10-13 18:14:00

+4

由於格式字符串通常更像是「價格是%4d」,而不是「%4d」,我仍然看到很多混淆的可能性。你有什麼對靜態方法? :) – FlySwat 2008-10-13 18:20:13

2

這兩種解決方案都可以模擬printf,但方式不同。 例如,將值轉換爲十六進制的字符串,你有2個以下解決方案:

  • format(),最接近sprintf()

    final static String HexChars = "abcdef"; 
    
    public static String getHexQuad(long v) { 
        String ret; 
        if(v > 0xffff) ret = getHexQuad(v >> 16); else ret = ""; 
        ret += String.format("%c%c%c%c", 
         HexChars.charAt((int) ((v >> 12) & 0x0f)), 
         HexChars.charAt((int) ((v >> 8) & 0x0f)), 
         HexChars.charAt((int) ((v >> 4) & 0x0f)), 
         HexChars.charAt((int) (v  & 0x0f))); 
        return ret; 
    } 
    
  • replace(char oldchar , char newchar),有點快,但相當有限:

    ... 
        ret += "ABCD". 
         replace('A', HexChars.charAt((int) ((v >> 12) & 0x0f))). 
         replace('B', HexChars.charAt((int) ((v >> 8) & 0x0f))). 
         replace('C', HexChars.charAt((int) ((v >> 4) & 0x0f))). 
         replace('D', HexChars.charAt((int) (v  & 0x0f))); 
        ... 
    
  • 還有第三個解決方案只包含廣告鼎的char ret一一(字符是彼此相加數字!),如:

    ... 
    ret += HexChars.charAt((int) ((v >> 12) & 0x0f))); 
    ret += HexChars.charAt((int) ((v >> 8) & 0x0f))); 
    ... 
    

...但是這會是真的