2012-05-03 52 views
4

我已經編寫如下一樣,我可以在循環內使用字符串文字嗎?

for(int i=0 ; i<n; i++){ 

String a = someObject.getFirstName(); //may not come same value.. 
doManipulationon(a); 
} 

在代碼審查,人們要求我刪除字符串字面a並直接使用someObject.getFirstName()進行操縱。他們擔心每次迭代都會在堆中創建字符串對象。

這是正確的方法嗎?

我認爲將getter分配給字符串變量會使代碼更具可讀性。

回答

4

首先這裏沒有字符串字面值。

字符串文字是用雙引號括起來的字符串表達式,如「dog」。

您的評論者指出他們不喜歡臨時變量a用於保存您在下一行中操作的表達式。

顯然,他們要你說

doManipulationon(someObject.getFirstName()); 

刪除臨時變量導致更緊湊的代碼。這通常是,但並非總是一個好主意。當您的「中間表達式」具有有意義的含義時,您可以使用臨時變量,但在您的情況下,使用名稱a沒有幫助。你可能會說

String firstname = someObejct.getFirstName(); 

在長表達式中,尤其是給部分結果賦予賦予有意義名稱的變量確實增加了可讀性。

哦,並且關於他們對在你的例子中添加到堆中的新字符串對象的評論---不,不會。

2

你是問你是否可以寫一個循環爲:

for(int i=0; i < n; i++) { 
    doManipulation(someObject.getFirstName()); 
} 

?如果是這樣,肯定是的。但是,a而不是一個字符串文字 - 它只是一個變量名稱。使用它只會將基礎字符串(位於堆上)的引用推送到堆棧上 - 無論您是否有變量a,都會發生這種情況(即它會在代碼版本中發生我也寫了)。即使不這樣做,將參考推入堆棧也很便宜,無關緊要。但無論哪種方式,字符串將堆在堆上,因爲字符串是對象,並且對象生活在堆上。

所以它只是一種風格,如果你覺得它更易於將字符串賦值給一個變量,那麼一定要這樣做。它還可以使調試更容易,因爲您可以在doManipulation行放置斷點並在進入該函數之前查看輸入。 (即使沒有分配,你也可以做到這一點,但它稍微不方便。)

+1

我喜歡你的答案,但你有一件事是錯誤的:字符串(和一般的對象)並不總是在堆中 - 實際的字符串(例如字符串文字)生活在PermGen中,它不屬於該區域稱爲堆(請參閱http://stackoverflow.com/a/2051778/1162168) –

+0

@MichaelSchmeißer是的,我們稱之爲「堆」甚至不是[堆數據結構](http:// en。 wikipedia.org/wiki/Heap_(data_structure))在Java!使用分代GC(這是HotSpot使用的),新分配的對象存在於更接近堆棧的內存塊中,除了只能清除它(不彈出單個項目)。儘管如此,我還是試圖讓答案變得簡單。 – yshavit

0

您可以使用下面的命令來檢查出的字節碼:

>javap -c -classpath /path/to/your/class/file classname 

有不同的是,你的代碼有兩個字節碼指令:

astore_2 // store a reference into local variable 2 

aload_2 // load a reference onto the stack from local variable 2 

所以,你的代碼是好的而它的確切作用並不像其他人所說的那樣

「他們害怕字符串對象將在堆前夕創建ry 迭代。「

1

他們害怕字符串對象將在堆上創建每個 迭代。

如果這是他們真正關心的問題,他們不知道他們在說什麼。當且僅當someObject.getFirstName()創建新的字符串時,將在堆上創建新字符串。創建一個臨時變量來保存參考不會創建一個新的字符串。

臨時變量花費一個堆棧槽。所有堆棧槽都在方法開始時分配,而不是在使用時分配。所以臨時變量的空間成本是4-8字節;時間成本是商店和負載;並且堆成本爲零。

相關問題