我应该让java Objects Null吗?

时间:2012-03-02 17:59:57

标签: java android object garbage-collection

假设我正在迭代一个对象数组,即

for (int r = 0; r < rows; r++) {
        for (int c = 0; c < columns; c++) {

            if (bricks[r][c] != null) {
                bricks[r][c].draw(gl)

如果我在某个时刻想破坏砖块,我的remove()方法应该使对象无效,如:

private void remove(GameBrick obj) {
     for (int r = 0; r < rows; r++) {
        for (int c = 0; c < columns; c++) {
        if (bricks[r][c] != null){
        if (bricks[r][c] == obj) {
            bricks[r][c] = null;
        } 

或者它应该将标记boolean exists设置为false,并且在迭代对象时,如果return添加continuebricks[r][c].exists == false语句?

目前我的代码基于使对象和空值检查无效,但后来我读到了垃圾收集器,并且将对象设置为null使其更频繁地运行。

我想知道这是否属实,以及我应该做些什么来删除对象(如果我应该这样做)。

7 个答案:

答案 0 :(得分:4)

  

但后来我读到了关于垃圾收集器和设置的问题   object to null使它更频繁地运行。

不,那是纯粹的传闻。最好的方法是假设GC已经过优化,可以根据需要经常运行,以便在性能和内存使用之间取得最佳平衡。

设置对null的引用是向GC发出不再需要该对象的信号的方式。 GC不必立即采取任何措施。

<强>更新

要调整应用程序的性能,您必须测量整个应用程序的行为 - 这意味着您必须首先编写整个应用程序(或非常逼真的端到端模型)。微优化不起作用。

因此,最好的方法是让GC完成它的设计 - 通过自动内存管理,使您可以轻松编写清晰,简单,易于修改的代码。这样,当您在目标计算机/设备上测试了应用程序并且可以看到需要调整性能的位置时,可以轻松地进行必要的更改而不会破坏任何内容。

性能优化必须由测量驱动。必须在完整产品的现实原型上进行测量。因此,在您的首次实现中,请专注于编写易于修改的代码。然后测量,并将凌乱的黑客只放入实际需要它们的地方。

请记住,根据您运行的设备,它们可能需要位于不同的位置!在某些设备上,在特定位置应用的黑客可能会降低您的速度,而在另一台设备上则会加速您的速度。因此,您不能盲目地在代码中随处遵循规则。你必须衡量。

答案 1 :(得分:3)

  

我后来读到了垃圾收集器,并且将对象设置为null会使其更频繁地运行。

事实并非如此。垃圾收集器定期运行,当JVM内存不足时。通过设置对null的引用,您只能增加GC释放的内存量,并减少它的工作量,因为java中使用的GC类型是O(|非垃圾内存) |)

增加释放的内存量会减少O(|非垃圾内存|),这只会使JVM内存不足,并且对定期运行没有影响。

  

我应该最好删除对象(如果我应该这样做的话)?

当不再需要对象的引用时,将其设置为null。构建函数,以便花费很长时间的函数调用尽可能少地参数。构造你的类,使它们松散耦合 - 其结果之一是长寿命对象的成员很少。这样做一致,您将成为JVM实现者优化的最佳位置。

答案 2 :(得分:2)

您希望在游戏中尽可能多地防止GC时间。不要将它们置空,建立一个池,标记死池,而不是实例化新的,从池中挑选一个死的并恢复它。

答案 3 :(得分:1)

是,将引用设置为null。这将导致垃圾收集器为您的应用程序释放更多内存。将引用设置为null不会导致垃圾收集器更频繁地运行,但它肯定会帮助它释放更多内存。

答案 4 :(得分:1)

答案将取决于您的特定代码,但通常对于Android游戏,您希望避免尽可能多的垃圾收集和对象创建(有关详细信息,请参阅here)。

您知道您拥有的砖块的最大行数和列数吗?你会经常摧毁和制造砖块吗?如果是这样,你可能最好在前面分配所有砖块,并使用布尔值来指示砖块是否有效。

答案 5 :(得分:0)

将附加到bricks容器时,考虑将位置r / c存储在砖块中。然后你不必搜索,只需看看砖内。这假定您最多可以将砖块添加到容器中一次。

在包含对象的生命周期长于代码范围的所有情况下,请将引用设置为null。不需要设置为null局部变量,这将隐含在范围的末尾(块“}”的结尾)。

答案 6 :(得分:0)

首先,直接回答你的问题:将引用设置为null没有任何内在错误。 请注意,您实际上并未将对象设置为null,而是将对象的引用设置为null,(或者如果您想要迂腐,则是对象引用的值)

在你的特定情况下,这是一个好主意是一个不同的故事。您当然可以通过不分配或释放对象来最小化垃圾收集(请参阅this Google I/O presentation)。我有兴趣从其他似乎不同意的人那里看到相反的证据。如果您的2D数组是砖块的唯一引用,则将其设置为null将取消引用该对象。解除引用对象可能不会让GC更频繁地运行(我不确定那个,尽管我读过的所有文献都建议避免在Android游戏循环中取消引用和分配),肯定会分配。

如果你的砖块总是在同一个位置并且它们被摧毁(如Breakout / Arkanoid)那么你的布尔标志想法可能是一个好主意。在这种情况下,您的2D数组有点像固定大小的池。

如果你的砖块可以改变位置,你可以做同样的事情并在移动时交换砖头,但有时候通常添加/删除可能更自然。在这种情况下,您应该预先在池中分配砖块,然后您可以在2D阵列中清空引用而不必担心垃圾收集,因为您的池仍然保留了引用(但是您需要先将它释放回池中)。