1

在编程时,我经常会遇到以下场景(在代码中描述)。我在要使用的块中定义变量。

    int maximumLengthOfToken = 0;

    while(fileScanner.hasNextLine())
    {
       String line; // definition
       line = fileScanner.nextLine();

       Scanner lineScanner; // definition
       lineScanner = new Scanner(line);

       String token = lineScanner.next(); // definition and assignment
       if(stringToMatch.endsWith(token))
        {
                 if(token.length() >= maximumLengthOfToken )
                  {
                     maximumLengthOfToken = token.length();  
                     builder.append(line);
                     builder.append("\n\n\n");
                  }
        }
    }
    fileScanner.close();

然而,有时,为了“整洁”,也因为我来自 C 背景,我喜欢在顶部定义所有变量,无论它们在哪里使用。所以我做了以下 -

    int maximumLengthOfToken = 0;
    String line; // definition
    Scanner lineScanner; // definition
    String token; // definition

    while(fileScanner.hasNextLine())
    {
       line = fileScanner.nextLine();
       lineScanner = new Scanner(line);

       token = lineScanner.next(); // definition

               if(stringToMatch.endsWith(token))
                {
                 if(token.length() >= maximumLengthOfToken )
                  {
                     maximumLengthOfToken = token.length();  
                     builder.append(line);
                     builder.append("\n\n\n");
                  }
        }
    }
    fileScanner.close();

“啊!它看起来很整洁”,我想。

但是,这对代码的性能有什么影响吗?第一种风格会导致更快的代码执行还是第二种风格?另外,在这种情况下,约定是什么?我相信这是第一种风格。

4

6 回答 6

4

不会。不会有性能差异。

如果您对此表示怀疑,请问问自己:“如果我的变量在 2000 字节之外,计算机查找我的变量会比在 200 字节或 20 字节之外需要更长的时间吗?” 答案应该是否定的。

唯一可能产生影响的情况是,如果您的变量在使用之前从处理器缓存中退出(请参阅局部性),在这种情况下,将变量移动到更靠近使用它的位置可能会提高速度。但是在变量和它的使用之间需要大量的代码才能实现。

编译器也有可能将您的方法编译为相同的字节码。简而言之,我认为您不必担心。

于 2012-04-06T22:05:05.790 回答
2

正如其他人所说,没有显着的性能差异。

您想在将变量声明放在方法顶部和将它们放在使用它们的位置之间进行选择。不要强迫自己做出这样的选择。你可以两者兼得——通过使你的方法非常简短。当您发现自己面临这种选择时,请将其视为您的代码告诉您:“您的方法太长了。”

更短的方法更容易编写、更容易测试、更容易调试、更容易维护。如果您没有(比如说)10 行以上的方法,您将永远不会遇到这个问题——并且您将拥有更好的组织代码。

于 2012-04-06T22:46:00.990 回答
1

这可能对代码的性能没有任何影响——我希望生成的字节码是相同的——但第一个版本通常被认为更易于维护和可读。

于 2012-04-06T22:05:10.247 回答
0

在一般情况下,可能会有轻微的(有时甚至是巨大的)差异,但在 Java 的情况下,标准编译器链很可能不会。

编译器可能会有所不同的是,您在一个范围内定义了“varA”,而在不相交的范围内定义了“varB”。编译器可能会观察到范围是不相交的,并将相同的堆栈槽分配给两者,这非常非常轻微地提高了解释器的性能。但是,如果它不够聪明,无法弄清楚发生了什么,这种技术可能会在 JITC 中导致更糟糕的优化。

于 2012-04-06T22:07:36.600 回答
0

由于在现代 Java 实现中使用了运行时优化,您应该不会看到太大的差异。因此,您应该主要关注清晰度和易于维护。

也就是说,有几个充分的理由将变量声明为尽可能接近使用位置:

  • 它更容易阅读,尤其是对于非常短暂的(例如临时)变量。读者可以立即看到变量的类型,而无需向上滚动到方法的开头。

  • 通过尽可能地限制变量的范围,您可以减少例如重用循环计数器时出现意外错误的可能性。

  • 当变量的范围尽可能有限时,一些优化(例如逃逸分析)可能会执行得更好。

作为旁注,我同时使用 C 和 Java 编程,有时很难从一个上下文切换到另一个。但是,在 Java 中使用 C 风格的约定(反之亦然)并不是一个好主意。C 约定是由 Java 根本没有的限制决定的——使用它们只会使您的代码更难被其他人阅读。

于 2012-04-06T22:38:02.797 回答
0

关于变量范围的最大“性能”差异将在垃圾收集中。在本地声明变量可能会允许 GC 更快地收集未使用的变量。

于 2012-04-07T00:26:00.677 回答