实例和迭代,哪一个更好?

9
我想要阅读文件并处理它们。每次迭代都会处理一个文件。
哪种代码更好?
1.
BufferedReader br;
for(File f : files)
{
    br = new BufferedReader(......);
    ......
}

2.
for(File f : files)
{
    BufferedReader br = new BufferedReader(......);
    ......
}

我的观点是哪一个在空间和速度方面更有效率?

1
@FedericoCristina 头部更新 (y) - Mukul Goel
6个回答

11

在我看来,后者更清晰明了。通常情况下,应尽可能使用最小范围声明局部变量,并在声明时初始化。

这不会直接影响性能,但会影响可读性和可维护性,从而影响您进行更改的轻松程度,这些更改将影响性能。

总的来说:

  • 确定您的性能和行为要求(以及如何测试两者)
  • 编写实现所需行为的最简单、最清晰的代码
  • 查看它是否满足性能要求
  • 如果不满足,请分析问题所在并进行“最少不洁”更改以改善情况(这可能意味着进行设计更改而非微观优化)
  • 重复执行上述步骤,直到您获得既符合性能要求又尽可能清洁的代码。

打印这个答案并把它挂在我的小隔间里。 - Steve's a D

5
  1. 它们完全相同,在编译成字节码后,所有差异都会丢失。
  2. 即使我们想象最坏的情况,理论上可能会增加一次额外的内存写入,但差异也非常小,你需要世界上精度最高的原子钟才能测量它。
  3. 对于您来说,真正的区别应该在于代码的整体可维护性,这应该比实际速度差异低于2-3%更重要。例如,许多设计模式引入了某种开销,但人们非常愿意为其提供的代码基础的灵活性付出代价。

在代码优化中,很容易陷入“赢得小,输得大”的陷阱:每个单独的方法可能被优化到完美,但由于全局架构的不足,整个系统的性能仍可能是一场灾难。必须始终自上而下地进行优化,当这样做时,您会发现只有1%或更少的代码行实际上可以通过优化版本替换来为总体性能做出贡献。


如果我没记错的话,第1点是错误的:在第二个例子中,循环结束后br不再被定义,一旦离开定义它的作用域。这使得维护更加容易,因为您不能意外地重复使用变量。 - Izkata
@izkata 1) 不是关于维护上的差异,而是关于运行时效率。编译器很容易检测到br的使用以for循环结束,并将其视为在内部声明。 - Marko Topolnik

3

如果您不在其他地方使用br变量,那么它们完全相同。

注意不要浪费太多时间尝试微小的优化。即使字节码不同,JIT在优化明显时也不会太差。您不需要在使用变量的块之前声明变量,并且不应该这样做,因为这会使其用途不太清晰。


1
唯一的区别是第二种情况下的 br 作用域仅限于循环内部,而在第一种情况中它可以在循环外部访问。但请注意,即使在第一种情况下,br 引用变量也将在循环外部可用,并不会保存你在for循环中赋予它的值。
否则它们是完全相同的。虽然第二种情况更易读。

0

3.

for(File f : files)
{
    try( BufferedReader br = new BufferedReader(......) )
    {
        ......
    }
}

0

就效率而言,两种方法大致相同,大多数情况下编译成的字节码也相似。

就可读性而言,第二种方法更好。通常情况下,当代码变得越来越复杂时,这种方法会有很大帮助。特别是在调试时,您不必担心该变量稍后在该块之外被修改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接