【问题标题】:PMD: Avoid instantiating new objects inside loopsPMD:避免在循环内实例化新对象
【发布时间】:2013-06-24 19:02:35
【问题描述】:

我遇到了 PMD 规则 Avoid instantiating new objects inside loops 的问题。下面是一些示例代码:

import java.awt.Dimension;

public class PMDDemo {
    public static void main(final String[] args) {
        final Dimension[] arr = new Dimension[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new Dimension(i, i); // rule violation here
        }
    }
}

PMD 在代码中的标记位置向我提供了上述违反规则的情况。我应该如何创建一个类的 n 个实例而不在循环中创建它们?

我知道 PMD 的一些规则是有争议的(例如 onlyOneExit 规则)。但到现在为止,我至少明白了他们背后的想法。我不明白这条规则背后的原因。有人可以帮我吗?

【问题讨论】:

标签: java loops instantiation pmd


【解决方案1】:

对于您的特定用例,在循环之后 保留对新对象的引用是没有意义的。因此,您的解决方案没有真正的替代方案。

更一般地说,creating short lived objects in Java is cheap*(除了 GC 会更频繁地运行的隐藏成本)。特别是分配几乎是免费的,GC 的时间主要取决于可到达对象的数量——对于典型的 GC 算法,死对象不会增加 GC 时间。

如果 JIT 检测到创建了不必要的对象,它还可以执行各种优化。

显然,不推荐创建无用对象,但尝试重用对象通常会适得其反。

作为一个实际示例,您可以查看this post,它表明在循环中创建一个新集合比在循环之前创建一个并在每次迭代时清除它更便宜。

* 感谢@RichardTingle 提供链接

【讨论】:

    【解决方案2】:
    for (int i = 0; i < arr.length; i++) {
      arr[i] = new Dimension(i, i); // rule violation here
    }
    

    上面的Pmd可以通过

    解决
     for (int i = 0; i < arr.length; i++) {
       arr[i] = createNewDimension(i,i); // rule violation here
     }
    
     private static Dimension createNewDimension(i,i) {
       return new Dimension(i, i);
     }
    

    我们不应该直接在循环中使用 new 操作符,而是将它移动到私有方法中。

    【讨论】:

    • 感谢您的意见。您真的更喜欢已解决的版本(带有创建包装器)吗?我认为这会降低它的可读性。但也许我错过了一些东西。 +1 用于实际解决违规行为。
    • 简单地将对象的创建包装在一个方法中实际上并不能阻止循环内的实例化。这只是对规则实施的颠覆。
    • 这实际上有助于解决无法避免在循环内创建对象时的 pmd 冲突。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    相关资源
    最近更新 更多