Я использую SonarLint, что показывает мне проблему в следующей строке.Встроенное форматирование строк и конкатенация строк в качестве параметра регистрации
LOGGER.debug("Comparing objects: " + object1 + " and " + object2);
Боковое примечание: метод, содержащий эту строку, может часто вызываться.
описания для этого вопроса
«Предпосылки» и аргументы лесозаготовительных не должны требовать оценки (кальмара: S2629)
Передачи аргументов сообщений, которые требуют дальнейшей оценки в Гуава com.google. common.base. Проверка условий может привести к штрафу . Это потому, что независимо от того, нужны они или нет, каждый аргумент должен быть разрешен до вызова метода.
Аналогично, передавая сцепленные строки в метод регистрации может также влечет за собой ненужный удар по производительности, так как конкатенация будет выполняется каждый раз, когда метод вызывается, или не является достаточно низким, чтобы показать сообщение уровень журнала .
Вместо этого вы должны структурировать свой код для передачи статических или предварительно вычисленных значений в состояние Предварительные условия проверки и регистрации вызовов.
В частности, встроенные в строке форматировании следует использовать вместо конкатенации, и если сообщение является результатом вызова метода , то Предпосылки должны быть пропущены altoghether и соответствующее исключение следует условно выброшены вместо.
Noncompliant Пример кода
logger.log(Level.DEBUG, "Something went wrong: " + message); // Noncompliant; string concatenation performed even when log level too high to show DEBUG messages LOG.error("Unable to open file " + csvPath, e); // Noncompliant Preconditions.checkState(a > 0, "Arg must be positive, but got " + a); // Noncompliant. String concatenation performed even when a > 0 Preconditions.checkState(condition, formatMessage()); //Noncompliant. formatMessage() invoked regardless of condition Preconditions.checkState(condition, "message: %s", formatMessage()); // Noncompliant
Compliant Решение
logger.log(Level.SEVERE, "Something went wrong: %s", message); // String formatting only applied if needed logger.log(Level.SEVERE,() -> "Something went wrong: " + message); //since Java 8, we can use Supplier , which will be evaluated lazily LOG.error("Unable to open file {}", csvPath, e); if (LOG.isDebugEnabled() { LOG.debug("Unable to open file " + csvPath, e); // this is compliant, because it will not evaluate if log level is above debug. } Preconditions.checkState(arg > 0, "Arg must be positive, but got %d", a); // String formatting only applied if needed if (!condition) { throw new IllegalStateException(formatMessage()); // formatMessage() only invoked conditionally } if (!condition) { throw new IllegalStateException("message: " + formatMessage()); }
Я не 100% уверен, понимают ли я на это право. Так почему же это действительно проблема. Особенно это касается эффективности производительности при использовании конкатенации строк. Потому что я часто читаю, что конкатенация строк быстрее, чем форматирование.
EDIT: Может быть, кто-то может объяснить мне разницу между
LOGGER.debug("Comparing objects: " + object1 + " and " + object2);
И
LOGGEr.debug("Comparing objects: {} and {}",object1, object2);
в фоновом режиме. Потому что я думаю, что String будет создана до того, как будет передан методу. Правильно? Так что для меня нет разницы. Но очевидно, что я не прав, потому что SonarLint жалуется на это
Ответ Икаро говорит о том, что конкатенация строк намного быстрее. Поэтому мне интересно, почему это проблема. О StringBuilder -> если вы видите комментарий AmirRaminar в ответе Икаро, то утверждает, что «+» преобразуется в вызовы StringBuilder компилятором – Naxos84
следующий комментарий для меня интереснее;) – luso