【问题标题】:Can i use string literal inside for loop?我可以在 for 循环中使用字符串文字吗?
【发布时间】:2012-05-03 05:24:45
【问题描述】:

我的编码如下,

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

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

在代码审查期间,人们要求我删除字符串文字 a 并直接使用 someObject.getFirstName() 进行操作。他们担心每次迭代都会在堆中创建字符串对象。

这是正确的方法吗?

我认为将 getter 分配给字符串变量会使代码更具可读性。

【问题讨论】:

    标签: java string


    【解决方案1】:

    首先这里没有字符串字面量。

    字符串文字是用双引号括起来的字符串表达式,例如“dog”。

    您的审阅者表示他们不喜欢临时变量 a 用于保存您在下一行操作的表达式。

    显然他们想让你说

    doManipulationon(someObject.getFirstName());
    

    删除临时变量会导致代码更紧凑。这通常是一个好主意,但并非总是如此。当您的“中间表达式”具有有趣的含义时,您可以使用临时变量,但在您的情况下,使用名称 a 没有帮助。你可以说

    String firstname = someObejct.getFirstName();
    

    尤其是在长表达式中,将部分结果分配给具有有意义名称的变量确实会增加可读性。

    哦,关于他们在您的示例中关于将新字符串对象添加到堆中的评论 --- 不,不会。

    【讨论】:

      【解决方案2】:

      您是在问是否可以将循环编写为:

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

      ?如果是这样,肯定是的。但是,a 没有 字符串文字——它只是一个变量名。使用它只会将一个对底层字符串(在堆上)的引用推送到堆栈上——不管你有没有变量a,都会发生这种情况(也就是说,它会发生在我写的代码也是)。即使没有,将引用推送到堆栈上也很便宜,这并不重要。但无论哪种方式,字符串都将在堆上,因为字符串是对象,而对象存在于堆上。

      所以它只是一种风格,如果你发现将 String 分配给一个变量更具可读性,那么一定要这样做。它还可以使调试更容易,因为您可以在doManipulation 行放置一个断点并在进入该函数之前查看输入。 (即使没有赋值也可以这样做,但只是不太方便。)

      【讨论】:

      • 我喜欢你的回答,但你有一个问题:字符串(和一般的对象)并不总是在堆上 - 实习字符串(如字符串文字)存在于 PermGen 中,这不是称为堆的区域的一部分(请参阅stackoverflow.com/a/2051778/1162168
      • @MichaelSchmeißer 是的,我们所说的“堆”在 Java 中甚至不是 heap data structure!使用分代 GC(这是 HotSpot 使用的),新分配的对象存在于更接近堆栈的内存块中,除了您只能清除它(不能弹出单个项目)。尽管如此,我还是试图让答案变得简单。
      【解决方案3】:

      他们担心每个字符串对象都会在堆中创建 迭代。

      如果这是他们真正关心的问题,他们不知道自己在说什么。 当且仅当 someObject.getFirstName() 创建一个新字符串时,才会在堆上创建一个新字符串。创建一个临时变量来保存 reference 不会创建一个新字符串。

      临时变量占用一个堆栈槽。所有堆栈槽都在方法开始时分配,而不是在使用时分配。所以临时变量的空间成本是4-8个字节;时间成本是一次存储和一次加载;并且堆成本为零。

      【讨论】:

        【解决方案4】:

        您可以使用以下命令来检查字节码:

        >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
        

        所以,你的代码没问题,它的作用并不像其他人说的那样

        “他们担心字符串对象会在每个 迭代。”

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-08
          • 1970-01-01
          相关资源
          最近更新 更多