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

Вызов метода Java vs с использованием переменной

Недавно я вошел в дискуссию с моей командой о том, как использовать временные переменные против вызова методов getter. Я давно придерживался мнения, что, если я знаю, что мне придется много раз называть простой метод getter, я бы поставил его в временную переменную, а затем использовал эту переменную. Я думал, что это будет лучше как с точки зрения стиля, так и с точки зрения производительности. Однако мой руководитель отметил, что в Java 4 и более новых версиях это было неверно. Он верит в использование меньшего пространства переменных, поэтому он сказал мне, что использование методов getter имеет очень незначительное влияние на производительность, а не на использование переменной temp, и, следовательно, использование getters было лучше. Однако я не полностью убежден в его аргументах. Что вы, ребята, думаете?

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

Это зависит. Если вы хотите дать понять, что вы используете одно и то же значение снова и снова, я бы присвоил его переменной temp. Я бы сделал так, если бы вызов геттера был несколько длинным, например myCustomObject.getASpecificValue().

У вас будет меньше ошибок в коде, если он будет читабельным. Итак, это главное.

Различия в производительности очень малы или не существуют.

Ответ 5

Если вы сохраняете эволюцию кода, простые геттеры в версии 1.0, как правило, становятся не столь простыми геттерами в версии 2.0.

Кодер, который меняет простой getter на не очень простой getter, обычно не имеет понятия, что существует функция, которая вызывает этот getter 10 раз вместо 1 и никогда не исправляет его там и т.д.

Вот почему с точки зрения DRY main имеет смысл кэшировать значение для повторного использования.

Ответ 6

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

Извините за нетехнический ответ.

Ответ 7

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

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

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

Ответ 8

Не стоит, если это просто getFoo(). Кэшируя его в переменную temp, вы не делаете ее намного быстрее и, возможно, задаете проблемы, потому что getFoo() может вернуть другое значение позже. Но если это что-то вроде getFoo().getBar().getBaz().getSomething(), и вы знаете, что значение не будет изменено в блоке кода, тогда может возникнуть причина использовать временную переменную для лучшей читаемости.

Ответ 9

Замечание общего порядка. В любой современной системе, за исключением ввода-вывода, не беспокойтесь о проблемах с производительностью. Яркие быстрые процессоры и кучи памяти означают, что все остальные проблемы в большинстве случаев совершенно несущественны для реальной производительности вашей системы. [Конечно, есть исключения, такие как кэширующие решения, но они далеки и редки.]

Теперь, придя к этой конкретной проблеме, да, компилятор включит все получатели. Тем не менее, даже это не является фактическим соображением, что действительно важно, так это над всеми читабельностью и потоком вашего кода. Замена локальных переменных лучше, если вызов используется несколько раз, например customer.gerOrder(). GetAddress() лучше фиксируется в локальной переменной.

Ответ 10

Виртуальная машина может обрабатывать первые четыре локальные переменные более эффективно, чем любая локальная переменная, объявленная после этого (см. lload и lload_ <n> инструкции). Таким образом, кэширование результата (inlined) getter может повредить вашей производительности.

Конечно, сами по себе либо влияние на производительность почти ничтожно, поэтому, если вы хотите оптимизировать свой код, убедитесь, что вы действительно занимаетесь фактическим узким местом!

Ответ 11

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

Ответ 12

Я поддерживаю использование переменной temp, если вы уверены, что getter вернет одинаковое значение во всей области. Потому что, если у вас есть переменная с именем длиной 10 или более, получатель выглядит плохо в аспекте читаемости.

Ответ 13

Я тестировал его в очень простом коде:

  • создал класс с простым getter из int (я пробовал как с окончательным, так и с конечным значением для Num, не видел никакой разницы, помните, что он в случае num никогда не изменяется также...!):

    Num num = new Num(100_000_000);
    
  • сравнил 2 разных для петель:

    1: for(int i = 0; i < num.getNumber(); ++i){(...)}
    
    2: number = num.getNumber();
    for(int i = 0; i < number; ++i){(...)}
    

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