声纳“对本地变量无用的分配”解决方法?

时间:2017-05-22 14:07:47

标签: java null sonarqube sonar-runner

我正在努力改进我的代码,我从Sonar遇到了这个问题:

Remove this useless assignment to local variable "uiRequest"

事实是,它并没有用,因为我在代码之后使用它:

        // I am supposed to remove this
        UiRequest uiRequest = null;

        if("Party".equals(vauban.getName()))   {
            uiRequest = contextBuilder.buildContext(vauban);
        } else {
            // Maybe I could work my way around here ?
            throw new NamingException(
                    String.format(
                            "Hey %s, change your name to %s, thanks",
                            vauban.getName(), "Vauban"));
        }

        // Set the generated Id in the result of context builder
        MyOwnService response = callService(uiRequest, vauban);

        return response;
声纳仍然告诉我“uiRequest”没用,为什么?它不是,因为如果它为null,我不希望它到达代码。我尝试初始化它(uiRequest = new UiRequest()),但它一直告诉我它没用。

任何人都知道为什么Sonar会像这样/如何纠正这个?

4 个答案:

答案 0 :(得分:4)

您可以通过以下方式避免出现警告,并且可能具有稍微可读的代码:

// I am supposed to remove this
//    UiRequest uiRequest = null;  <-- remove

// invert the test here
    if(! "Party".equals(vauban.getName()))   {
        // Maybe I could work my way around here ?
        throw new NamingException(
                String.format(
                        "Hey %s, change your name to %s, thanks",
                        vauban.getName(), "Vauban"));
    } 

    // you are only using the variable in the call service; make
    //   final since reference should not change after assignment
    final UiRequest uiRequest = contextBuilder.buildContext(vauban);

    // Set the generated Id in the result of context builder
    MyOwnService response = callService(uiRequest, vauban);

    return response;

答案 1 :(得分:4)

您的问题简化为:

Foo x = null;

if(a()) {
     x = b();
} else {
     throw new Exception();
}

c(x);

此代码有两种可能的路径:

  1. a()返回truex已分配b(),然后调用c(x)
  2. a()返回false。抛出异常并且不调用c(x)
  3. 这两个路径都没有使用c(x)的初始分配来调用null。所以无论你最初分配什么,都是多余的。

    请注意,如果初始赋值不是null,那么这也是一个问题。除非作业的右侧有副作用,否则任何作业都会被浪费。 (声纳分析副作用)

    这对Sonar来说是可疑的:

    • 也许程序员期望第一个任务产生效果 - 它没有,所以也许这是一个错误。
    • 这也是代码清晰度 - 代码的未来人类读者可能会浪费时间来了解初始值是什么。
    • 如果右侧涉及计算,但没有副作用,则会浪费计算。

    您可以通过两种方式解决此问题:

    首先只删除= null,离开Foo x; - Java非常聪明地认识到c(x)的所有路由都涉及一个赋值,所以这仍然会编译。

    更好的是,将c(x)移到块中:

    if(a()) {
         Foo x = b();
         c(x);
    } else {
         throw new Exception();
    }
    

    这在逻辑上是等同的,更整洁,并且缩小了x的范围。缩小范围是一件好事。当然,如果您在更广泛的范围内需要 x,则无法执行此操作。

    另一种变体,在逻辑上等同于:

    if(! a()) {
       throw new Exception();
    }
    
    Foo x = b();
    c(x);
    

    ...对“提取方法”和“内联”重构做出了很好的反应:

    throwForInvalidA(...);
    c(b());
    

    使用最适合您的意图。

答案 2 :(得分:1)

如何将其移入if语句?

    if("Party".equals(vauban.getName()))   {
        UiRequest uiRequest = contextBuilder.buildContext(vauban);
        // Set the generated Id in the result of context builder
        MyOwnService response = callService(uiRequest, vauban);
        return response;
    } else {
        throw new NamingException(
                String.format(
                        "Hey %s, change your name to %s, thanks",
                        vauban.getName(), "Vauban"));
    }

或者在if语句中抛出异常,并且没有else子句。即正常情况下是&#34;快乐的道路&#34;。

答案 3 :(得分:0)

分配没用,因为没有代码可以看到指定的值。