在循环内部或外部声明变量
2022-08-31 05:23:45
为什么以下工作正常?
String str;
while (condition) {
str = calculateStr();
.....
}
但是这个据说是危险的/不正确的:
while (condition) {
String str = calculateStr();
.....
}
是否有必要在循环外部声明变量?
为什么以下工作正常?
String str;
while (condition) {
str = calculateStr();
.....
}
但是这个据说是危险的/不正确的:
while (condition) {
String str = calculateStr();
.....
}
是否有必要在循环外部声明变量?
在你的示例中,我假设没有在循环外部使用,否则您就不会提出问题,因为在循环内声明它不是一个选项,因为它不会编译。str
while
while
因此,由于 不在循环外部使用,因此 最小的可能范围是在 while 循环内。str
str
因此,答案是绝对应该在 while 循环中声明。没有如果,没有和,没有但是。str
可能违反此规则的唯一情况是,如果由于某种原因,必须从代码中挤出每个时钟周期至关重要,在这种情况下,您可能需要考虑在外部作用域中实例化某些内容并重用它,而不是在内部作用域的每次迭代中重新实例化它。但是,由于java中字符串的不可变性,这不适用于您的示例:str的新实例将始终在循环的开头创建,并且必须在循环结束时将其丢弃,因此无法在那里进行优化。
编辑:(在答案下面注入我的评论)
无论如何,正确的做事方法是正确编写所有代码,为产品建立性能要求,根据此要求衡量最终产品,如果它不满足它,那么就去优化它。通常最终会发生的事情是,你找到方法在几个地方提供一些漂亮而正式的算法优化,使我们的程序满足其性能要求,而不必遍历整个代码库,调整和破解东西,以挤压这里的时钟周期。
我比较了这两个(类似)示例的字节码:
让我们看一下 1. 示例:
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.java
javap -c Test
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.示例:
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.java
javap -c Test
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 规范的结果...
但是,以最佳编码实践的名义,建议在尽可能小的范围内声明变量(在此示例中,它位于循环内部,因为这是使用变量的唯一位置)。