Преждевременная оптимизация в Java: когда использовать «x = foo.getX ()» вместо простого «foo.getX ()»

Когда я несколько раз вызываю один и тот же метод получения, это должно считаться проблемой? Лучше ли [всегда] присваивать локальную переменную и вызывать только один раз?

Я уверен, что ответ, конечно, «это зависит».

Меня больше беспокоит более простой случай, когда геттер просто метод типа "передача значения частной переменной". т. е. не требуются дорогостоящие вычисления, не используются соединения с базой данных и т. д.

Мой вопрос «лучше» относится как к читаемости (стилю) кода, так и к производительности. то есть, это большая часть попадания в производительность:

SomeMethod1(a, b, foo.getX(), c);
SomeMethod2(b, foo.getX(), c);
SomeMethod3(foo.getX());

против:

X x = foo.getX();
SomeMethod1(a, b, x, c);
SomeMethod2(b, x, c);
SomeMethod3(x);

Я понимаю, что этот вопрос немного придирчив и сер. Но я только что понял, у меня нет последовательного способа оценки этих компромиссов, вообще. Я ловлю рыбу по некоторым критериям, которые более чем просто капризны.

Спасибо.

13
задан Aaron Fi 31 August 2010 в 19:31
поделиться

5 ответов

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

У меня, однако, есть принцип размещения операторов в одной строке, что очень часто приводит к тому, что такие выражения, как "foo.getBar()", становятся слишком длинными. Тогда для меня более читабельно извлечь его в локальную переменную ("Bar bar = foo.getBar()").

8
ответ дан 1 December 2019 в 18:54
поделиться

Это зависит от того, что на самом деле делает getX(). Рассмотрим этот класс:

public class Foo {
    private X x;

    public X getX() { return x; }
}

В этом случае, когда вы вызываете foo.getX(), JVM оптимизирует его вплоть до foo.x (как в прямая ссылка на приватное поле foo, в основном указатель памяти). Однако, если класс выглядит следующим образом:

public class Foo {
    private X x;

    public X getX() { return cleanUpValue(x); }

    private X cleanUpValue(X x) {
        /* some modifications/sanitization to x such as null safety checks */
    }
}

JVM больше не может встраивать его так же эффективно, поскольку по конструктивному контракту Foo он должен дезинфицировать x перед передачей это из.

Подводя итог, если getX() на самом деле ничего не делает, кроме возврата поля, то нет никакой разницы после того, как первоначальная оптимизация выполняется для байт-кода, в том, вызываете ли вы метод только один раз или несколько раз.

3
ответ дан 1 December 2019 в 18:54
поделиться

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

3
ответ дан 1 December 2019 в 18:54
поделиться

Обычно я сохраняю его локально, если:

  1. Я буду использовать его в цикле и не хочу или не ожидаю изменения значения во время цикла.

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

  3. Я хочу переименовать переменную, чтобы она лучше соответствовала поставленной задаче.

  4. Тестирование указывает на значительный прирост производительности.

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

2
ответ дан 1 December 2019 в 18:54
поделиться

В большинстве случаев я бы использовал getX, если это было только один раз, и создал для него переменную для всех остальных случаев. Часто просто для того, чтобы не печатать.

Что касается производительности, компилятор, вероятно, сможет оптимизировать большую часть накладных расходов, но возможность побочных эффектов может заставить компилятор выполнять больше работы при выполнении нескольких вызовов методов.

2
ответ дан 1 December 2019 в 18:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: