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

Вызов геттеров на объект и сохранение его как локальной переменной (объем памяти, производительность)

В следующем фрагменте кода дважды вызываем listType.getDescription():

for (ListType listType: this.listTypeManager.getSelectableListTypes())
{
    if (listType.getDescription() != null)
    {
        children.add(new SelectItem( listType.getId() , listType.getDescription()));
    }
}

Я хотел бы реорганизовать код для использования одной переменной:

for (ListType listType: this.listTypeManager.getSelectableListTypes())
{
    String description = listType.getDescription();

    if (description != null)
    {
        children.add(new SelectItem(listType.getId() ,description));
    }
}

Мое понимание JVM как-то оптимизировано для исходного кода и особенно вложенных вызовов типа children.add(new SelectItem(listType.getId(), listType.getDescription()));.

Сравнение двух опций, какой из них является предпочтительным и почему? То есть с точки зрения объема памяти, производительности, удобочитаемости/легкости и других, которые мне сейчас не приходят.

Когда последний фрагмент кода становится более выгодным по сравнению с первым, то есть есть (приблизительное) количество вызовов listType.getDescription(), когда использование локальной переменной temp становится более желательным, поскольку listType.getDescription() всегда требует некоторых операций стека для хранения объекта this?

4b9b3361

Ответ 1

Я почти всегда предпочитаю решение локальной переменной.

Объем памяти

Одна локальная переменная стоит 4 или 8 байтов. Это ссылка и нет рекурсии, поэтому пусть игнорирует ее.

Производительность

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

читаемость

Следуйте принципу DRY. В вашем случае это вряд ли имеет значение, так как имя локальной переменной по-символу примерно столько же, сколько вызов метода, но для чего-то более сложного, это читаемость, поскольку вам не нужно найти 10 различий между этими двумя выражениями. Если вы знаете, что они одинаковы, дайте понять, используя локальную переменную.

Корректность

Представьте, что ваш SelectItem не принимает null, и ваша программа многопоточна. Значение listType.getDescription() может меняться тем временем, и вы поджарились.

Отладка

Наличие локальной переменной, содержащей интересное значение, является преимуществом.


Единственное, что можно выиграть, опуская локальную переменную, - это сохранение одной строки. Поэтому я бы сделал это только в тех случаях, когда это действительно не имеет значения:

  • очень короткое выражение
  • невозможна одновременная модификация
  • простой закрытый конечный получатель

Ответ 2

Я думаю, что способ номер два определенно лучше, потому что он улучшает удобочитаемость и ремонтопригодность вашего кода, что является самым важным здесь. Такая микро-оптимизация ничем не поможет, если вы не напишете приложение, где важна каждая миллисекунда.

Ответ 3

Я не уверен, что это предпочтительнее. То, что я бы предпочел, - явно читаемый код поверх кода исполнителей, особенно когда это увеличение производительности незначительно. В этом случае я подозреваю, что там нет заметной разницы (особенно учитывая оптимизацию JVM и возможности перезаписи кода).

Ответ 4

В контексте императивных языков значение, возвращаемое вызовом функции, не может быть сохранено (см. http://en.m.wikipedia.org/wiki/Memoization), потому что нет гарантии что функция не имеет побочного эффекта. Соответственно, ваша стратегия действительно позволяет избежать вызова функции за счет выделения временной переменной для хранения ссылки на значение, возвращаемое вызовом функции. В дополнение к тому, чтобы быть немного более эффективным (что не имеет большого значения, если функция не вызвана много раз в цикле), я бы выбрал ваш стиль из-за лучшей читаемости кода.

Ответ 5

Я бы согласился с подходом локальной переменной для чтения, только если имя локальной переменной самодокументировано. Назвать его "описание" будет недостаточно (какое описание?). Вызов "selectableListTypeDescription" дал бы понять. Я бы добавил, что добавленная переменная в цикле for должна быть названа "selectableListType" (особенно если "listTypeManager" имеет аксессоры для других типов ListTypes).

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