我正在努力改进我的代码,我从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"是没有用的,为什么?它不是,因为如果它是空的,我不希望它到达代码。我尝试初始化它(uiRequest = new UiRequest()
),但它一直告诉我它是无用的。
任何人都知道为什么声纳会这样/如何纠正这一点?
您的问题简化为:
Foo x = null;
if(a()) {
x = b();
} else {
throw new Exception();
}
c(x);
此代码有两种可能的路径:
a()
返回true
.x
被分配b()
然后调用c(x)
。a()
返回false
.引发异常且不调用c(x)
。
这些路径调用都不c(x)
使用null
的初始分配。因此,无论您最初分配什么,都是多余的。
请注意,如果初始赋值不是 null,这也将是一个问题。除非作业的右侧有副作用,否则任何作业都会被浪费。(副作用的声纳分析)
这对声纳来说是可疑的:
- 也许程序员期望第一个作业有效果 - 它没有,所以也许它是一个错误。
- 这也与代码清晰度有关 - 未来的代码读者可能会浪费时间想知道初始值的用途。
- 如果右侧涉及计算,但没有副作用,那将是浪费计算。
您可以通过两种方式解决此问题:
首先只是删除= 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());
使用最能传达您的意图的方法。
您可以通过以下方式避免警告,并可能拥有更具可读性的代码:
// 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;
把它移到 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 子句。 即让正常情况成为"快乐之路"。
赋值是无用的,因为没有代码可以看到分配的值。