2013-04-04 47 views
0

另一個question回答了我如何在編譯時計算字符串文字的連接。在我正在開發的一個項目中,我們使用StringBuffer來處理大型查詢的多行字符串。它只是附加文字,所以它讓我想到是否會發生類似的事情。文字的字符串分配

在下面的代碼中,緩衝區會在編譯時追加它的內容嗎?當多線程嘗試執行此功能時,這將如何表現?

public static String querySomething(int arg){ 


     StringBuffer buffer = new StringBuffer(); 
     buffer.append("A quite long query"); 
     buffer.append("that doesn't fit in one line"); 
     buffer.append("..."); 

    } 

那豈不是更好地定義String爲常數,因爲這將是線程安全的,我們知道它可以在編譯時與加運算得到串聯。喜歡的東西:

private final static REALLY_LONG_QUERY1 = "A quite long query that" 
              +"doesn't fit in one line" 
              +"..."; 
+2

由於'StringBuffer'在方法**中被聲明爲**,所以如果此方法被多個線程同時調用,它將不會被考慮在內。你甚至可以用'StringBuilder'替換它,並且具有相同的行爲(開銷較小)。 – 2013-04-04 13:47:14

回答

3

那豈不是更好地定義字符串作爲常數...

基本上是這樣。

...因爲它是線程安全的,我們知道它可以在編譯時與加號運算符連接。

這些斷言都是正確的。

但是,您不需要擔心代碼版本中的線程安全性,因爲它的代碼版本爲StringBuffer

  • StringBuffer類是線程安全的。
  • 如果StringBuffer實例只對一個線程可見(例如調用聲明和使用該實例的方法的線程),則實例爲線程被限制爲並且不需要是線程安全的數據結構。 (你可以使用StringBuilder,而不是...)

的使用+串聯文字版本的主要優點是,它需要零時間在運行時,並不會引起對象的分配...除了表示在加載類時分配的連接字符串常量的一個String對象。


事實上,在很多地方人們明確使用StringBuilderStringBuffer「優化」字符串連接,它要麼沒有效果,或者實際上使代碼慢:

  • 由於您注意到,Java編譯器在編譯時評估字面串聯(使用+),但它不能爲顯式StringBuilder.append調用做同樣的事情。

  • 此外,Java編譯器通常會將表達式中的非常量字符串並置(使用+)轉換爲使用StringBuilder的等效代碼。

唯一的情況下,這是值得使用StringBuilder明確的是,當刺痛建設跨越多個報表;例如因爲你在一個循環中連接了一些東西。

+0

我並不擔心線程安全性,因爲我知道'StringBuffer'是線程安全的,但是這意味着更多的內存將被分配?每個線程有一個新實例? – Sednus 2013-04-04 13:56:51

+0

每次運行時,StringBuffer版本都會分配一個新的StringBuffer對象...除非您嘗試重用現有對象。 (如果你這樣做,你確實需要擔心多線程......) – 2013-04-04 13:59:51

+0

我的意思是StringBuffer ...更正。 – 2013-04-04 14:01:48

0

在下面的代碼,將緩衝在編譯時添加的內容?

是的。

當多個線程試圖執行此功能時,這會如何表現?

沒有問題,因爲每個線程會用它自己的StringBuffer(它是在方法中聲明)。

將字符串定義爲常量不是更好嗎?

是的,這樣做會更有意義。

+0

在上面的例子中,自從你的第一條語句之後,'StringBuffer'提供的線程安全性不會被考慮:*每個線程都會使用它自己的'StringBuffer' *。 – 2013-04-04 13:50:21

+0

StringBuffer線程的安全性是無關緊要的 - 變量是在方法體內聲明的,因此它只能在該線程中使用該方法(除非進一步傳遞等)。 – Dariusz 2013-04-04 13:50:24

+0

每個線程都會使用它自己的'StringBuilder'這是否意味着我將爲每個線程分配一個新的'StringBuffer'?這與其他選擇相比如何? – Sednus 2013-04-04 13:50:44

1

我寧願第二種解決方案(僅使用+運營商)。

爲什麼?這是因爲:

  • 更多可讀(今日面向功能編程,時尚,高效)
  • 更多官能避免無用的(臨時)局部變量和特別是可變的變量(如buffer是)。
0

StringBuffer的配合更好,當你想建立一個字符串,你不知道在編譯時的實際大小,例如:

public static String querySomething(int arg) { 
    StringBuffer buffer = new StringBuffer(); 
    while (...) { 
     buffer.Append(someStuff()); 
    } 
} 

在你的情況,恆定更適合。

+0

StringBuffer在編譯時不會構建字符串。 – EJP 2013-04-05 00:24:00

+0

是的,我的意思是運行時間...謝謝(更正) – 2013-04-05 09:33:51