将需要进一步评估的消息参数传递到 Guava com.google.common.base.Preconditions 检查可能会导致性能下降。这是因为无论是否需要它们,每个参数都必须在实际调用方法之前解决。
同样,将连接的字符串传递给日志记录方法也会导致不必要的性能损失,因为每次调用该方法时都会执行连接,无论日志级别是否低到足以显示消息。
相反,您应该构建代码以将静态或预先计算的值传递到前提条件检查和记录调用。
具体来说,应该使用内置字符串格式而不是字符串连接,如果消息是方法调用的结果,则应该完全跳过前置条件,而是有条件地抛出相关异常。
不合规代码示例
logger.log(Level.DEBUG, "Something went wrong: " + message);
// Noncompliant; string concatenation performed even when log level too high to show DEBUG messages
logger.fine("An exception occurred with message: " + message);
// Noncompliant
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: {0} ", message);
// String formatting only applied if needed
logger.fine("An exception occurred with message: {}", message);
// SLF4J, Log4j
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 {0}", 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());
}
例外
catch 块被忽略,因为性能损失在异常路径上并不重要(catch 块不应成为标准程序流的一部分)。 Getter 以及在注释上调用的方法都被忽略,这些方法可以被视为 getter。此规则说明使用 SLF4J 方法 isXXXEnabled 进行显式测试级测试,并忽略此类 if 语句的主体。