Вызов геттера несколько раз или один раз и присвоение переменной? - PullRequest
13 голосов
/ 12 мая 2010

предположим, у меня есть класс как:

public class Age {

    private int age;

    public int getAge() {
       return this.age;
    }

}

В моем основном классе я много раз вызываю метод getAge().

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

Что лучше и почему?

Ответы [ 12 ]

10 голосов
/ 12 мая 2010

Вероятно, это ситуация, когда вы оптимизируете, прежде чем вы знаете, что вам нужно. Значение является целым числом, поэтому оно не занимает много памяти, если вы храните значение в нескольких местах. В то же время это очень простой вызов метода, выполнение которого не займет много времени. Напишите это так, чтобы вы чувствовали себя наиболее читабельно. Затем, после того как у вас будет надежная версия кода, вы можете использовать инструмент профилирования, чтобы увидеть, есть ли заметная разница.

7 голосов
/ 12 мая 2010

Не пытайтесь микрооптимизировать это, если только вы не обнаружите, что это действительно узкое место при профилировании. Я бы использовал метод доступа getAge (), так как это, скорее всего, наиболее приемлемое и очевидное решение.

При этом два подхода, вероятно, будут работать в точности одинаково. Во время выполнения JIT, скорее всего, полностью оптимизирует вызов getAge (), поэтому в обоих случаях это будет единственный примитивный доступ.

3 голосов
/ 12 мая 2010

Это то, что вы, как автор API, должны указать вызывающей стороне.

В общем, если вы просто возвращаете свойство, вы можете пометить вызов как окончательный (если вы не предлагаете фактический интерфейс). Это должно снизить затраты на вызовы, так как компилятор с большей вероятностью встроит функцию.

Если стоимость расчета свойства высока (например, поиск строки), запишите его в JAvaDocs для этого метода и укажите вызывающей стороне, что он может захотеть получить значение один раз и кэшировать его.

3 голосов
/ 12 мая 2010

Может быть некоторое снижение производительности при вызове метода getAge() много раз, но я предлагаю вам рассмотреть Печальная трагедия театра микрооптимизации .

2 голосов
/ 12 мая 2010

Не беспокойся. Это абсолютно не стоит микро-оптимизации, как это. Подождите, пока вы закончили свой код, затем он работает слишком медленно, затем достаньте профилировщик и поработайте над тем, что, по словам профилировщика, является источником проблемы.

Преждевременная оптимизация - корень всего зла.

1 голос
/ 12 мая 2010

В зависимости от того, как разработано ваше приложение, эти два варианта могут фактически давать разные результаты! Если используемый вами возрастной возраст является общим и изменяемым, в разных местах вашего приложения его значение может измениться между вызовами на getAge(). В этом случае вопрос правильности выбора наилучшего варианта для вашего кода зависит от вас, и вам решать. Как гласит старая пословица: «сначала сделай это правильно, а потом сделай это быстро». И, как уже упоминали другие, вам, вероятно, не нужно будет беспокоиться о том, чтобы «сделать это быстро» в этом случае.

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

1 голос
/ 12 мая 2010

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

В том случае, если вы представили вызов getAge (), он очень прост, а стоимость вызова почти равна нулю. Не беспокойтесь об этом в этом случае.

Но если ваш getAge был чем-то необычным, который делает много вычислений или получает доступ к ресурсам ввода-вывода, например:

public int getAge() {
   return slowService.calculateAgeByBirthDate(birthDate); // it takes 2 seconds to execute for every call
}

Тогда наверняка неплохо было бы кешировать результат и использовать его. Потому что, если вы позвоните 30 раз, ваш код займет 1 минуту.

0 голосов
/ 21 мая 2010

В этом случае я бы посоветовал не смотреть на производительность, а на удобство использования и повторное использование кода. Ваша текущая реализация - самая простая из методов получения, которая возвращает целое число.

Но что, если где-нибудь внизу вы сохраните дату рождения человека и захотите динамически определить возраст? Если вы просто вызываете свойство напрямую, вы вынуждены рефакторинг своего кода. Однако, изменяя внутренние функции getAge (), вы можете поместить вычисление туда, и все готово.

Мне бы очень хотелось, чтобы языки программирования представили «суперприватный» модификатор свойства / поля, который по сути говорит: «Вы можете получить доступ к этому свойству только через его метод доступа».

0 голосов
/ 13 мая 2010

Вы не увидите значительных изменений в производительности, если не будете выполнять много операций внутри метода getAge ().

0 голосов
/ 13 мая 2010

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

Если, например, данный метод не переопределен в подклассе, его можно рассматривать точно так же, как и конечный метод, позволяя JVM встроить копию своего кода в вызывающий метод вместо явного вызова метода , (Если условия меняются, эти классы затем просто считаются новыми и, следовательно, перекомпилируются позже на основе новых условий).

Это означает, что get / set для атрибутов bean (где значения просто хранятся и извлекаются, а не вычисляются) очень дешевы, и вы должны выполнять вызовы каждый раз и ожидать, что JVM обнаружит возможные оптимизации и применит их. 1005 *

...