Подтвердить что ты не робот

PMD: избегать создания новых объектов внутри циклов

У меня проблема с правилом 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). Но до сих пор я по крайней мере понял идею, стоящую за ними. Я не понимаю причины этого правила. Может ли кто-нибудь помочь мне с этим?

4b9b3361

Ответ 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);
 }

мы не должны напрямую использовать новый оператор внутри цикла, просто переместите это внутри частного метода.