SonarQube:仅有条件地调用方法

时间:2017-06-02 08:48:11

标签: java logging sonarqube

以下部分代码引发了SonarQube的一个主要错误: “只是有条件地调用方法。”
我该如何解决这个问题?

if(us != null){
    logger.info("Log this: {}", us.toString());
}

4 个答案:

答案 0 :(得分:15)

@echo off setlocal call :prompt "Fill in the blank:" response echo You entered "%response%" call :prompt "This is a prompt of a different length:" response echo You entered "%response%" <NUL set /P "=Press any key to exit. " & pause >NUL & echo; goto :EOF :prompt <question> <return_var> setlocal disabledelayedexpansion set "dots=................................................................................" for /f "skip=4 tokens=2 delims=:" %%I in ('mode con') do if not defined cols ( set /a cols = %%I - 4 ) call set "dots=%%dots:~-%cols%%%" rem // credit: https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/AUXP8XbRAJA for /f %%a in ('copy /Z "%~dpf0" nul') do endlocal & set /P "%~2=%dots%%%a%~1 " & exit /b 的调用是多余的,无论配置的日志级别如何,都将调用us.toString()方法。您应该仅将toString()作为参数传递给us而不使用info语句。

if

答案 1 :(得分:7)

正如问题的评论所述,另一个有效的答案是:

if(logger.isInfoEnabled() && us != null){
    logger.info("Log this: {}", us.toString());
}

答案 2 :(得分:1)

您可以忽略它,但是如果可能的话,处理这种情况可能会很好,它将帮助我们处理和切断不必要的计算。

这里建议的一件事是检查您要使用的日志级别是否已启用。

if(logger.isInfoEnabled() && us != null){
    // this inner code will only get executed if the above is true
    logger.info("Log this: {}", us.toString());
}

想象一下,如果内部有一个复杂的任务正在运行,那么如果禁用了日志级别,那么无论如何都不打算记录它,那将是浪费时间。记录器将在内部为您检查,但现在在调用.info()之前执行此操作将为您节省一些时间。

答案 3 :(得分:1)

将需要进一步评估的消息参数传递给Guava com.google.common.base。前提条件检查可能会导致性能下降。这是因为无论是否需要它们,每个参数都必须在实际调用该方法之前进行解析。

类似地,将串联字符串传递到日志记录方法中也可能造成不必要的性能损失,因为无论日志级别是否足够低以显示消息,每次调用该方法时都会执行串联。

相反,您应该构建代码结构,以将静态或预先计算的值传递到Preconditions条件检查和记录调用中。

具体地说,应该使用内置的字符串格式而不是字符串连接,如果消息是方法调用的结果,则应该完全跳过前提条件,而应该有条件地抛出相关的异常。 / p>

不兼容的代码示例

    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块不应成为标准程序流程的一部分)。吸气剂以及在注解上调用的方法都可以被视为吸气剂,它们将被忽略。该规则说明了使用SLF4J方法isXXXEnabled进行的显式测试级测试,并忽略了此类if语句的主体。