首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在循环内部或外部声明变量

在循环内部或外部声明变量
EN

Stack Overflow用户
提问于 2012-01-10 21:01:16
回答 20查看 165.1K关注 0票数 262

为什么下面的代码可以正常工作?

代码语言:javascript
复制
String str;
while (condition) {
    str = calculateStr();
    .....
}

但是这个据说是危险的/不正确的:

代码语言:javascript
复制
while (condition) {
    String str = calculateStr();
    .....
}

是否有必要在循环外声明变量?

EN

回答 20

Stack Overflow用户

回答已采纳

发布于 2012-01-10 21:12:14

局部变量的作用域应该总是尽可能小。

在您的示例中,我假设str没有在while循环之外使用,否则您就不会问这个问题,因为在while循环中声明它是不可行的,因为它不会编译。

因此,由于没有在循环外部使用str,因此str的最小作用域是在while循环内。

因此,答案是绝对应该在while循环中声明str。没有如果,没有ands,没有但是。

可能违反此规则的唯一情况是,由于某些原因,必须将每个时钟周期挤出代码,这一点至关重要,在这种情况下,您可能希望考虑实例化外部作用域中的某些内容并重用它,而不是在内部作用域的每次迭代中重新实例化它。然而,这并不适用于您的示例,因为java中字符串的不可变性: str的新实例总是会在循环的开始处创建,并且必须在循环结束时将其丢弃,因此不可能在那里进行优化。

编辑:(在答案中插入我的评论)

在任何情况下,正确的做法是正确地编写所有代码,为您的产品建立一个性能需求,根据这个需求来衡量您的最终产品,如果它不能满足它,那么就去优化它。通常最终发生的是,你找到了一些方法,在几个地方提供一些好的和正式的算法优化,使我们的程序满足其性能要求,而不是不得不遍历整个代码库,调整和修改东西,以便在这里和那里压缩时钟周期。

票数 314
EN

Stack Overflow用户

发布于 2012-01-16 17:39:49

我比较了这两个(类似)示例的字节代码:

让我们看一下1. 示例

代码语言:javascript
复制
package inside;

public class Test {
    public static void main(String[] args) {
        while(true){
            String str = String.valueOf(System.currentTimeMillis());
            System.out.println(str);
        }
    }
}

在使用javac Test.javajavap -c Test之后,您将获得:

代码语言:javascript
复制
public class inside.Test extends java.lang.Object{
public inside.Test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   3:   invokestatic    #3; //Method java/lang/String.valueOf:(J)Ljava/lang/String;
   6:   astore_1
   7:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  aload_1
   11:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   14:  goto    0

}

让我们看一下2.示例

代码语言:javascript
复制
package outside;

public class Test {
    public static void main(String[] args) {
        String str;
        while(true){
            str =  String.valueOf(System.currentTimeMillis());
            System.out.println(str);
        }
    }
}

在使用javac Test.javajavap -c Test之后,您将获得:

代码语言:javascript
复制
public class outside.Test extends java.lang.Object{
public outside.Test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   3:   invokestatic    #3; //Method java/lang/String.valueOf:(J)Ljava/lang/String;
   6:   astore_1
   7:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  aload_1
   11:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   14:  goto    0

}

观察结果表明,这两个例子之间没有差异。这是JVM规范的结果……

但出于最佳编码实践的考虑,建议在尽可能小的范围内声明变量(在本例中,变量在循环内,因为这是使用变量的唯一位置)。

票数 314
EN

Stack Overflow用户

发布于 2012-01-22 04:26:47

在最小的作用域中声明对象可以提高的可读性

对于今天的编译器来说,性能并不重要。(在这个场景中)

从维护的角度来看, option 选项更好。

在同一位置声明和初始化变量,并尽可能缩小作用域。

正如Donald Ervin Knuth所说:

“我们应该忘记小的效率,比如说97%的时间:过早的优化是一切邪恶的根源”

即,程序员让性能考虑因素影响一段代码的设计的情况。这可能会导致设计不像原本那样干净的,或者代码不正确,因为优化使代码变得复杂复杂(),并且程序员被优化分散了注意力。

票数 31
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8803674

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档