Что более эффективно при проверке переменной java с помощью null?

Какой лучший способ проверить varName на null и вызвать имя метода methodName2?

void methodName(String varName) {
    if (varName == null) {
        return;
    }
    methodName2();
}
//or 
void methodName(String varName) {
    if (varName != null) {
        methodName2();
    }
}
void methodName2() {
    // do the stuff
}

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

Murat Karagöz 18.10.2018 12:34

Возможный дубликат Проверить, не является ли строка не пустой и не пустой

Vivek Mishra 18.10.2018 12:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
2
52
3

Ответы 3

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

void methodName(String varName) {
    if (varName == null) {
        return;
    }

    methodName2();
}

Я предпочитаю это, потому что null явно обрабатывается как случай, когда methodName() просто возвращается без каких-либо дополнительных действий. Во второй версии окончательное поведение такое же, но из кода оно менее очевидно. Кроме того, вторая версия оставляет потенциальные проблемы с обслуживанием. Предположим, кто-то наследует ваш код и ему нужно добавить функциональность:

void methodName(String varName) {
    if (varName != null) {
        methodName2();
    }

    // let's make the method do something else
}

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

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

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

Есть только один способ убедиться. Протестируйте его с помощью jmh.

(Мне кажется, что JIT-компилятор сможет создавать собственный код для двух версий, которые идентичны по производительности. Это не должно быть так сложно ...)

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

Более того, вы можете обнаружить, что «микро» производительность зависит от деталей, которые обычно находятся вне вашего контроля:

  • Дополнительные версии JRE
  • различия в поведении разных наборов микросхем из-за различий в конвейере, разных размеров кеш-памяти L1 и L2 и т. д.
  • разные размеры физической памяти и кучи

Ваши микрооптимизации для одной JRE, набора микросхем и т. д. Могут на самом деле ухудшить ситуацию на более новой JRE, другом наборе микросхем и т. д.

Лучшая стратегия - оставить «микро» оптимизацию JIT-компилятору.

И если вам необходимость под рукой оптимизировать:

  1. Создайте реалистичный тест для всего приложения (или библиотеки).
  2. Установите некоторую поддающуюся количественной оценке производительность цели.
  3. Заставьте программное обеспечение работать.
  4. Сравните это. Если это соответствует целям, СТОП!
  5. Профилируйте его, чтобы найти горячие точки.
  6. Выберите новую точку доступа для оптимизации. Если ничего не осталось, если процент потраченного времени достаточно велик, чтобы иметь значение, СТОП!
  7. Ручная оптимизация точки доступа.
  8. Тест / профиль снова. Это улучшило ситуацию? Если нет, ОТКРОЙТЕ оптимизацию.
  9. Повторить.

Другие вопросы по теме