11

“新”有多贵?我的意思是,我应该以重用同一个对象为目标,还是该对象“超出范围”与清空它一样?

例如,假设一个方法创建了一个列表:

List<Integer> list = new ArrayList<Integer>(); 

在方法结束时,列表不再使用 - 这是否意味着不再为其分配内存,或者是否意味着有一个空指针指向它(因为它是“创建的”)。

或者,我可以向该方法发送一个“列表”并在方法结束时将其清空:list.removeAll(list);从内存的角度来看,这会有什么不同吗?

谢谢!

4

6 回答 6

15

its an array list, so creating a new object means allocating a slab of memory and zeroing it, plus any bookkeeping overhead. Clearing the list means zeroing the memory. This view would lead you to believe that clearing an existing object is faster. But, it's likely that the JVM is optimized to make memory allocations fast, so probably none of this matters. So just write clear, readable code, and don't worry about it. This is java after all, not c.

于 2012-02-16T15:47:27.050 回答
4

在方法结束时,列表不再使用 - 这是否意味着不再为其分配内存,或者是否意味着有一个空指针指向它(因为它是“创建的”)。

意味着没有对它的引用,并且对象有资格进行 GC。

或者,我可以向该方法发送一个“列表”,并在方法结束时将其清空: list.removeAll(list); 从记忆的角度来看,这会有什么不同吗?

这是时间/空间之间的权衡。即使您不需要创建新对象,从列表中删除元素也很耗时。

使用最新的 JVM GC 收集功能,可以在需要时创建新对象(但最好避免在循环中创建对象)。对对象的较长引用有时会使该对象不符合 GC 条件,如果处理不当可能会导致内存泄漏。

于 2012-02-16T15:41:10.440 回答
2

这取决于对象的成本,包括所需的初始化以及它的内存占用量有多大。它还很大程度上取决于应用程序的类型(应用程序还花时间在什么地方)。

对于您使用 ArrayList 的示例,已经很难给出明确的答案 - 取决于列表中有多少条目, clear() 可能非常昂贵或非常便宜,而新的 ArrayList 的成本几乎不变。

一般的经验法则是:在您测量出存在性能问题之前,不要费心重用对象,然后非常确定创建对象是导致该问题的原因。您的应用程序中很可能有更多有价值的优化机会。分析器将帮助确定您花费最多时间的地方。专注于那些和更好的算法。

于 2012-02-16T17:10:10.720 回答
2

how expensive is 'new'?

It definitely incurs some overhead. But it depends on how complex the object is. If you are creating an object with just few primitives, not that expensive. But if you are creating objects inside objects, may be collections of objects, if your constructor is reading some properties file to initialize object's member variables, EXPENSIVE!

But to be frank, if we need to create a new object, we have create it, there is no alternative. And if we don't need to and if we are still creating that is kind of bad programming.

at the end of the method the list is no longer in use - does it mean that there's no memory allocated to it anymore or does it mean that there's a null pointer to it (since it was 'created').

Once the object does not have any reference to it, it becomes out of scope, and it becomes eligible for garbage collection. Hence even if it has some memory allocated, it will be reclaimed by the GC at some later point, whenever it runs, we need not worry about it. (And we cannot guarantee when will GC run).

Emptying the collection at the end, I don't think will make things any better, because the same thing will happen to all the individual objects in the collection, as what happens to the collection itself. They will become eligible for GC.

于 2012-02-16T15:48:39.287 回答
2

对于小型列表,它可能比列表便宜一点clear()

对于非常大的堆中非常大的列表的渐近情况,归结为 GC 是否可以比 can 中的for循环更快地清零一大块内存clear()。我认为它可能可以。

但是,我的建议是忽略这一点,除非您有令人信服的证据(来自分析)表明您的ArrayList对象周转率很高。(仅根据您的直觉进行优化是个坏主意。)

于 2012-02-16T16:02:04.890 回答
2

我对 java 中的内存占用了解不多,但我认为清空 List 以重用它并不是一个好主意,因为清空 List 会影响性能。而且我认为从面向对象的角度来看,这也不是一个好主意,因为您应该拥有一个只有一个目的的对象。

在方法结束时,对象确实超出了范围。但这并不意味着它已被垃圾收集,甚至有资格进行垃圾收集,因为其他人可能仍会引用该列表。所以基本上:如果没有对该列表的对象引用,那么它可能适合垃圾收集,但如果它会被垃圾收集它仍然不确定,如果列表仍然存储在年轻一代空间中,它可以在伊甸园中空间或永久空间。伊甸园空间是第一次分配对象的地方,当垃圾收集发生并且对象还活着时,它将被移动到幸存者空间。如果它仍然存在,它将转移到 Tenured 空间,我相信不会发生太多垃圾收集。但这一切都取决于一个对象的生命周期、谁引用了这个对象以及它被分配到哪里

于 2012-02-16T15:44:51.913 回答