声纳“对局部变量的无用赋值"解决方法?
我正在努力改进我的代码,我从 Sonar 中遇到了这个问题:
I am working towards improving my code, and I came across this issue from Sonar:
Remove this useless assignment to local variable "uiRequest"
事实上,它并不是没用的,因为我在代码中使用它:
Fact is, it is not useless, as I am using it just after in the code:
// 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;
Sonar 仍然告诉我uiRequest"没用,为什么?不是,因为如果它为空,我不希望它到达代码.我尝试初始化它(uiRequest = new UiRequest()
),但它一直告诉我它没用.
Sonar still tells me that "uiRequest" is useless, why ? It is not, as I don't want it to reach the code if it is null. I tried initializing it (uiRequest = new UiRequest()
) but it keeps telling me that it is useless.
有人知道声纳为什么会这样/如何纠正这个问题吗?
Anyone got an idea about why Sonar behaves like this / how to correct this ?
推荐答案
您的问题简化为:
Foo x = null;
if(a()) {
x = b();
} else {
throw new Exception();
}
c(x);
这段代码有两种可能的路径:
There are two potential paths through this code:
a()
返回true
.x
被分配b()
然后c(x)
被调用.a()
返回false
.抛出异常,c(x)
未被调用.
a()
returnstrue
.x
is assignedb()
thenc(x)
is called.a()
returnsfalse
. An exception is thrown andc(x)
is not called.
这些路径都没有使用 null
的初始分配调用 c(x)
.所以你一开始分配的任何东西都是多余的.
Neither of these paths calls c(x)
using the initial assignment of null
. So whatever you assigned at first, is redundant.
请注意,如果初始分配不是空值,这也是一个问题.除非赋值的右侧有副作用,否则任何赋值都是浪费的.(声纳分析副作用)
Note that this would also be an issue if the initial assignment was something other than null. Unless the right-hand-side of the assignment has a side effect, any assignment is wasted. (Sonar analyses for side-effects)
这对 Sonar 来说是可疑的:
This is suspicious to Sonar:
- 也许程序员期望第一个赋值有效果——它没有,所以也许这是一个错误.
- 这也关乎代码的清晰性——未来的人类阅读代码可能会浪费时间去思考初始值的用途.
- 如果右侧涉及计算,但没有副作用,那就是浪费计算.
您可以通过两种方式解决此问题:
You can fix this in two ways:
首先只是删除 = null
,留下 Foo x;
- Java 足够聪明地意识到所有到 c(x)
的路由涉及一个赋值,所以这仍然会编译.
Firstly just removing the = null
, leaving Foo x;
- Java is clever enough to realise that all routes to c(x)
involve an assignment, so this will still compile.
更好的是,将 c(x)
移动到块中:
Better yet, move c(x)
into the block:
if(a()) {
Foo x = b();
c(x);
} else {
throw new Exception();
}
这在逻辑上是等价的,更简洁,并且缩小了 x
的范围.缩小范围是件好事.当然,如果你需要 x
在更广泛的范围内,你不能这样做.
This is logically equivalent, neater, and reduces the scope of x
. Reducing scope is a good thing. Of course, if you need x
in the wider scope, you can't do this.
还有一个变体,在逻辑上也是等价的:
One more variation, also logically equivalent:
if(! a()) {
throw new Exception();
}
Foo x = b();
c(x);
...对提取方法"和内联"重构反应良好:
... which responds well to "extract-method" and "inline" refactorings:
throwForInvalidA(...);
c(b());
使用最能传达您的意图的那个.
Use whichever communicates your intent best.
相关文章