PMD:避免在循环内实例化新对象

2022-09-01 21:03:56

我有一个关于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的一些规则是有争议的(比如唯一的OneExit规则)。但到目前为止,我至少理解了他们背后的想法。我不明白这条规则背后的原因。有人可以帮我吗?


答案 1

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

更一般地说,在Java中创建短期对象是便宜的*(除了GC将更频繁地运行的隐性成本)。特别是,分配几乎是免费的,GC的时间主要取决于可访问对象的数量 - 对于典型的GC算法,死对象不会增加GC时间。

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

显然,创建无用的东西不是一种推荐的做法,但尝试重用对象往往会适得其反。

作为一个实际的例子,你可以看看这篇文章,它表明在循环中创建一个新集合比在循环之前创建一个并在每次迭代时清除它更便宜。

*感谢@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运算符,只需将其移动到私有方法中即可。


推荐