Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在循环内部或外部声明变量_Java_Optimization_While Loop - Fatal编程技术网

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

Java 在循环内部或外部声明变量,java,optimization,while-loop,Java,Optimization,While Loop,为什么下面的工作很好 String str; while (condition) { str = calculateStr(); ..... } 但这一条据说是危险的/不正确的: while (condition) { String str = calculateStr(); ..... } 是否有必要在循环外部声明变量?在while循环外部声明字符串str允许在while循环内部和外部引用它。在while循环中声明字符串str只允许在while循环中被引用。

为什么下面的工作很好

String str;
while (condition) {
    str = calculateStr();
    .....
}
但这一条据说是危险的/不正确的:

while (condition) {
    String str = calculateStr();
    .....
}

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

while
循环外部声明字符串
str
允许在
while
循环内部和外部引用它。在
while
循环中声明字符串
str
只允许
while
循环中被引用。

在内部,变量的可见范围越小越好。

如果您还想在looop外部使用
str
;在外面申报。否则,第二个版本就可以了。

如果不需要在while循环(范围相关)之后使用
str
,那么第二个条件就是

  while(condition){
        String str = calculateStr();
        .....
    }
更好,因为如果仅当
条件
为真时才在堆栈上定义对象。也就是说,如果需要,请使用它。

局部变量的范围应始终尽可能小。 在您的示例中,我假定
str
不会在
while
循环之外使用,否则您不会问这个问题,因为在
while
循环内声明它将不是一个选项,因为它不会编译

因此,由于
str
未在循环外使用,因此
str
的最小可能范围在while循环内

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

此规则可能违反的唯一情况是,如果由于某种原因,每一个时钟周期都必须从代码中挤出,在这种情况下,您可能需要考虑在外部范围内实例化某个对象并重用它,而不是在内部范围的每一次迭代上重新实例化它。但是,这不适用于您的示例,因为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);
        }
    }
}
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 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

}
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

}
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

}
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

}
外部公共类。Test扩展java.lang.Object{
公共外部测试();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
公共静态void main(java.lang.String[]);
代码:
0:invokestatic#2;//方法java/lang/System.currentTimeMillis:()J
3:invokestatic#3;//方法java/lang/String.valueOf:(J)Ljava/lang/String;
6:astore_1
7:getstatic#4;//字段java/lang/System.out:Ljava/io/PrintStream;
10:aload_1
11:invokevirtual#5;//方法java/io/PrintStream.println:(Ljava/lang/String;)V
14:转到0
}
观察结果表明,这两个例子之间没有差异。这是JVM规范的结果


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

确实,上述问题是编程问题。您希望如何编写代码?您需要在哪里访问“STR”?声明作为全局变量在本地使用的变量是没有用的。我相信编程的基础。

在最小范围内声明对象可以提高可读性

对于今天的编译器来说,性能并不重要。(在这种情况下)
从维护角度来看,2nd选项更好。
在尽可能狭窄的范围内,在同一位置声明和初始化变量

正如Donald Ervin Knuth所说:

“我们应该忘记小效率,比如说97%的时间: 过早优化是万恶之源“


i、 e)程序员让性能考虑因素影响代码设计的情况。这可能会导致设计不干净,或者代码不正确,因为优化会使代码变得复杂,程序员会因优化而分心。

这两个示例产生相同的结果。但是,第一个选项为您提供了在while循环之外使用
str
变量的功能;第二个不是。

变量的声明应尽可能接近它们的使用位置

这使RAII更容易


它使变量的范围保持紧密。这让优化器工作得更好。

正如许多人所指出的

String str;
while(condition){
    str = calculateStr();
    .....
}
不是比这个好:

while(condition){
    String str = calculateStr();
    .....
}

因此,如果不重复使用,不要在变量的作用域之外声明变量…

根据谷歌Android开发指南,变量的作用域应该是有限的。请检查此链接:

<
 String str;
    while(condition){
        str = calculateStr();
        .....
    }
while(condition){
    String str = calculateStr();
    .....
}
{
  // all tmp loop variables here ....
  // ....
  String str;
  while(condition){
      str = calculateStr();
      .....
  }
}