声纳 "useless assignment to local variable" 解决方法?
Sonar "useless assignment to local variable" workaround?
我正在努力改进我的代码,我从 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;
Sonar 仍然告诉我 "uiRequest" 没用,为什么?它不是,因为如果它为空,我不希望它到达代码。我尝试初始化它 (uiRequest = new UiRequest()
),但它一直告诉我它没用。
有人知道为什么 Sonar 会这样/如何纠正这个问题吗?
将它移到 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 子句。即让正常情况为 "happy path".
赋值是无用的,因为没有代码可以看到赋值。
您可以通过以下方式避免警告并可能使代码更具可读性:
// 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;
您的问题简化为:
Foo x = null;
if(a()) {
x = b();
} else {
throw new Exception();
}
c(x);
这段代码有两条可能的路径:
a()
returnstrue
。 x
被分配 b()
然后 c(x)
被调用。
a()
returnsfalse
。抛出异常,不调用c(x)
。
这些路径都没有使用 null
的初始分配调用 c(x)
。所以无论你一开始分配什么,都是多余的。
请注意,如果初始分配不是 null,这也会是一个问题。除非赋值的右侧有副作用,否则任何赋值都会被浪费。 (声纳分析副作用)
这对 Sonar 来说是可疑的:
- 也许程序员希望第一个赋值有效果——它没有,所以这可能是一个错误。
- 这还与代码清晰度有关——未来的代码人 reader 可能会浪费时间思考初始值的用途。
- 如果右边有计算,但没有副作用,那就是浪费计算。
您可以通过两种方式解决此问题:
首先只删除 = 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);
... 对 "extract-method" 和 "inline" 重构反应良好:
throwForInvalidA(...);
c(b());
使用最能传达您意图的那个。
我正在努力改进我的代码,我从 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;
Sonar 仍然告诉我 "uiRequest" 没用,为什么?它不是,因为如果它为空,我不希望它到达代码。我尝试初始化它 (uiRequest = new UiRequest()
),但它一直告诉我它没用。
有人知道为什么 Sonar 会这样/如何纠正这个问题吗?
将它移到 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 子句。即让正常情况为 "happy path".
赋值是无用的,因为没有代码可以看到赋值。
您可以通过以下方式避免警告并可能使代码更具可读性:
// 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;
您的问题简化为:
Foo x = null;
if(a()) {
x = b();
} else {
throw new Exception();
}
c(x);
这段代码有两条可能的路径:
a()
returnstrue
。x
被分配b()
然后c(x)
被调用。a()
returnsfalse
。抛出异常,不调用c(x)
。
这些路径都没有使用 null
的初始分配调用 c(x)
。所以无论你一开始分配什么,都是多余的。
请注意,如果初始分配不是 null,这也会是一个问题。除非赋值的右侧有副作用,否则任何赋值都会被浪费。 (声纳分析副作用)
这对 Sonar 来说是可疑的:
- 也许程序员希望第一个赋值有效果——它没有,所以这可能是一个错误。
- 这还与代码清晰度有关——未来的代码人 reader 可能会浪费时间思考初始值的用途。
- 如果右边有计算,但没有副作用,那就是浪费计算。
您可以通过两种方式解决此问题:
首先只删除 = 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);
... 对 "extract-method" 和 "inline" 重构反应良好:
throwForInvalidA(...);
c(b());
使用最能传达您意图的那个。