2012-05-03 49 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字节;时间成本是商店和负载;并且堆成本为零。

相关问题