2

我正在阅读Google 关于 Android 优化的提示,他们提出的第一点是您应该避免使用短期变量,因为这意味着更多的垃圾收集。那么,有没有一点你会更好地定义一个变量并使用它而不是每次你想使用该对象时调用一个访问器?说这个:

for(int i = 0; i < 1000; i++) {
    foo.getBar() // then do something with it
}

与此相反:

Bar bar = foo.getBar();
for(int i = 0; i < 1000; i++) {
    bar // then do something with it
}

性能方面有什么区别?

4

3 回答 3

3

从您提供的链接中:“您应该避免创建不需要的对象实例”

  1. 对象实例!=短期变量
  2. 不要忘记句子的第二部分...

局部变量通常在堆栈上分配(GC 无关紧要),而新的对象实例将在堆上分配 - 这是一个完全不同的故事。TMHO 说“如果你真的不需要,就不要做某事”这样的话没有什么价值。此外,尽可能避免创建局部变量可能会对您的代码产生非常糟糕的影响,请阅读此

于 2013-03-25T04:18:12.817 回答
2

假设没有编译器优化

当你使用

for(int i = 0; i < 1000; i++) {
    foo.getBar() // then do something with it
}

您的代码将转到由 引用的实例foo,执行其getBar()方法,然后该方法将返回它应该返回的任何实例/值。这将针对该循环的 1000 次执行中的每一次执行。每次执行完成后,返回的值getBar()都必须被垃圾回收。

但是,当您使用:

Bar bar = foo.getBar();
for(int i = 0; i < 1000; i++) {
    bar // then do something with it
}

foo.getBar()只获得一次的值,在循环之外并在本地存储它的副本。然后在循环中使用此本地副本 1000 次。

第二个选项更有效,因为您的foo实例的getBar()方法只被调用一次,而不是一千次。这意味着您不会将getBar()方法中的代码执行 1000 次,这显然比执行一次更糟糕。

这些都是真正的微观优化。除非您正在做一些真正的繁重工作getBar(),否则这不会产生明显的效果。在很多情况下,编译器优化会将这两个转换为完全相同的字节码,因此您无论如何都不必担心。

于 2013-03-25T03:57:10.977 回答
1

在这个例子中,假设 bar 只是一个由 getBar 返回的对象并且没有被创建,就 GC 而言没有区别。

但是,方法调用的开销也很小,您的第二个示例将更有效。

但是,如果 getBar 在每次调用时创建一个新对象,则将创建 1000 个新 Bar,然后在第二个示例中进行 GC,而第一个保持不变。

于 2013-03-25T03:59:50.430 回答