Java 编写高效代码和优化内存

Java 编写高效代码和优化内存,java,garbage-collection,coding-style,Java,Garbage Collection,Coding Style,我有两段代码(用Java编写),哪一段效率更高 int foo(){ int result; for(int i = 0; i < n;i++){ SomeObject a,b,c; a = new SomeObject(); b = new SomeObject(); c = new SomeObject(); //do something with a,b,c //and derive result

我有两段代码(用Java编写),哪一段效率更高

int foo(){

   int result;
   for(int i = 0; i < n;i++){
      SomeObject a,b,c;
      a = new SomeObject();
      b = new SomeObject();
      c = new SomeObject();
      //do something with a,b,c
      //and derive result
   }
   return result;
}
intfoo(){
int结果;
对于(int i=0;i

intfoo(){
int结果;
物体a、b、c;
a=新的SomeObject();
b=新的SomeObject();
c=新的SomeObject();
对于(int i=0;i
在第二个代码片段中,我将局部变量移出了循环,因此它实际上只创建了它们的一个实例。这有什么改善吗? 从逻辑上讲,当变量在循环中时,这是有意义的。但是垃圾收集器会有效地清理对象吗


编辑:更新了关于对象实例化的剪报。

如前所述,它们是相同的。在这两种情况下,当函数开始执行时,SomeObject引用的内存在函数的堆栈帧中分配一次

因此,请选择范围最有限的版本。这还有另一个好处——如果函数在循环结束后执行一项耗时的操作,那么SomeObject实例将在循环结束后立即符合GC的条件

但是请注意,如果一个或多个对象使用新的
初始化,并且在每个循环迭代中构造的对象都是相同的,并且是可重用的,则会有实质性的差异。那么,最好避免在每次循环迭代中不必要地创建和丢弃相同的对象

编辑以更新问题
FWIW,在这个细节上我不同意Jon Skeet的观点:考虑到更新后的问题,最好在循环之外构造对象,并在每次迭代中重用它们。如果方法中的另一个代码太复杂,以至于不需要重构,那么需要重构的是方法,而不是循环。

这取决于,如果它们在两个实例中的每次循环迭代中都被构造,那么两者都不是更有效的。如果在循环体外部初始化它们,则后一个将更快。

您已将变量移出,但这些不是对象。假设在循环的每次迭代中都为
a
b
c
分配不同的值,那么根本没有减少内存分配—只是不必要地扩大了变量的范围

如果您不需要在循环中更改
a
b
c
的值,那么这是另一回事,最好在循环外分配它们,而不是在每次迭代中

主要的是要认识到对象和变量之间的区别。特别是,在循环的每次迭代中创建“新”变量实际上并不需要任何成本

编辑:好的,对于更新后的问题,显然在创建多少对象方面存在差异。然而,根据具体情况,第二种形式可能更可取:它当然更容易理解,而且它不依赖于
flush
操作的细节。另一方面,如果创建
SomeObject
的实例成本很高(例如,它会生成加密密钥),那么最好针对这一点进行优化


简言之:视情况而定。首先编写可读性最高的代码,对其进行度量,并将其与性能要求进行比较。只有当有明显的好处时,才使用不太明显的代码。

垃圾收集确实可以有效地清理对象,但这并不意味着它是零成本的。在第二个例子中,你必须考虑的是,你必须有可变的对象,这些对象可以重新回到原来的状态,这也不是零成本。


大多数性能问题的答案是;编写尽可能清晰和简单的代码,结果也将具有良好的性能,这通常就足够了。如果您确实存在性能问题,请分析您的应用程序,以查看可能需要更改的内容。

我实际上已经对此进行了测试,没有区别,因为编译器发现选项1可以做得更好,就像选项2一样,并将其更改为该选项


代码首先是为了清晰,其次是为了效率(无论如何编译器都比你聪明)

但是在第二个版本中创建的SomeObject的实例数是n,而在第一个版本中是1。这有关系吗?@Codevalley:我最初的答案已经提到了这一点(请参见“但请注意……”)。我已经更新了我的答案来澄清。更新了问题。不知何故,我遗漏了初始化部分。这不是一个编辑使所有答案无效的情况吗?加油,加油!看看它有多好,基本上几乎没有人编辑问题,唯一的编辑实际上是改变问题。。。啊,等不及下一件大事了,因为这将成为一部喜剧。现在问题已经改变了,我认为这个答案是无效的。特别是创建了不同数量的
SomeObject
对象。
int foo(){

   int result;
   SomeObject a,b,c;
   a = new SomeObject();
   b = new SomeObject();
   c = new SomeObject();

   for(int i = 0; i < n;i++){
      a.flush(); //reset object do not create new though
      b.flush(); //reset object do not create new though
      c.flush(); //reset object do not create new though
      //do something with a,b,c
      //and derive result
   }
   return result;
}