Oracle Tutorial

ользуюSonarLint это показывает мне проблему в следующей строке.

LOGGER.debug("Comparing objects: " + object1 + " and " + object2);

Примечание: метод, содержащий эту строку, может вызываться довольно часто.

Описание этой проблемы

«Предварительные условия» и аргументы регистрации не должны требовать оценки (squid: S2629)

Передача аргументов сообщения, которые требуют дальнейшей оценки, в проверку com.google.common.base.Preconditions Guava может привести к снижению производительности. Это потому, что нужны они или нет, каждый аргумент должен быть разрешен до фактического вызова метода.

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

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

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

Пример несовместимого кода

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

Совместимое решение

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%, правильно ли я это понимаю. Так почему же это действительно проблема? Особенно часть о быстродействии при использовании конкатенации строк. Потому что я часто читаю, что конкатенация строк быстрее, чем ее форматирование.

РЕДАКТИРОВАТЬ: Может быть, кто-то может объяснить мне разницу между

LOGGER.debug("Comparing objects: " + object1 + " and " + object2);

А ТАКЖЕ

LOGGEr.debug("Comparing objects: {} and {}",object1, object2);

на заднем плане. Потому что я думаю, что String будет создан до того, как он будет передан методу. Правильно? Так что для меня нет разницы. Но, очевидно, я не прав, потому что SonarLint жалуется на это

Ответы на вопрос(3)

Ваш ответ на вопрос