sonar问题汇总
1.布尔常量使用
【问题标题】:How to fix the major issue in SonarQube "needlessly boxes a boolean constant"如何解决 SonarQube 中的主要问题“不必要地装箱一个布尔常量”
forexample
java">private static boolean isNAND(boolean value1, boolean value2) {
return value1 ? !value2 : Boolean.TRUE;
}
【解决方案1】:
(参数类型保持一致,避免不必要的拆箱和装箱)
java">private static boolean isNAND(boolean value1, boolean value2) {
return value1 ? !value2 : true;
}
【解决方案2】:
不使用布尔包装器
java">private static boolean isNAND(boolean value1, boolean value2) {
return value1 || !value2;
}
2.字符串的拼接设置
当一个类似的方法公开时,该方法将长度为1的常量字符串作为参数传递给一个方法。处理一个字符而不是字符串更简单、更方便。
This method passes a constant literal String of length 1 as a parameter to a method, when a similar method is exposed that takes a char. It is simpler and more expedient to handle one character, rather than a String.
java">String myString = ...
if (myString.indexOf("e") != -1) {
int i = myString.lastIndexOf("e");
System.out.println(myString + ":" + i); //the Java compiler will use a StringBuilder internally here [builder.append(":")]
...
return myString.replace("m","z");
}
Replace the single letter Strings with their char equivalents like so:
java">String myString = ...
if (myString.indexOf("e") != -1) {
// ==========================
int i = myString.lastIndexOf('e');
// ==========================
System.out.println(myString + ":" + i); //the Java compiler will use a StringBuilder internally here [builder.append(":")]
...
return myString.replace("m","z");
}
3.第三方包产生歧义的时候
此方法调用在第三方库中找到的方法,该方法似乎与另一个第三方的库不同。当jar包含使用maven shade插件等工具的其他代码时,就会出现这种情况。很可能您希望使用原始jar中的“一流”类,而不是具有着色包结构的类,但是IDE引入了错误的导入。
This method calls a method found in a 3rd-party library, which appears to be shaded from another 3rd-party library. This occurs when a jar includes other code that uses tools like the maven shade plugin. It is likely you wanted to use the “first-class” class from the original jar, rather than the class with the shaded package structure, but your IDE pulled in the wrong import.
- 问题分析:就是你导入的某个包下的某个方法,可能在第三方jar包中,有重名的,需要你再方法前面拼接一下全方法(类名+方法名)绝对路径
- An example might be, you attempted to use a method from the class:
com.google.common.collect.Sets
- But instead, you import:
x.xxx.xxxx.com.google.common.collect.Sets
4.使用常量索引访问列表或数组(accesses list or array with constant index)
This method accesses an array or list using a constant integer index. Often, this is a typo where a loop variable is intended to be used. If however, specific list indices mean different specific things, then perhaps replacing the list with a first-class object with meaningful accessors would make the code less brittle.
此方法使用常量整数索引访问数组或列表。通常,这是一个要使用循环变量的拼写错误。然而,如果特定的列表索引意味着不同的特定事物,那么用有意义的访问器替换一个一级对象可能会使代码不那么脆弱。
exam
p.setCode((String) fileds[1]);
p.setTitle((String) fileds[2]);
p.setLogo((String) fileds[3]);
p.setMaxBorrowAmt((Integer) fileds[4]);
p.setMinBorrowAmt((Integer) fileds[5]);
【解决方案1】:
Use a final Integer Constant instead
public static final Integer CODE_POSITION = 0;
//other code
p.setCode((String) fileds[CODE_POSITION]);
//rest of the code...
【解决方案2】:
Create Custom Class
public class CustomClass{
private String code;
private String title;
// rest goes here
//all setter getter
}
and then replace method signature List<Object[]> findSomething();
with List<CustomClass> findSomething();
And Access the listItem using below code snap.
p.setCode(listItem.getCode());
p.setTitle(listItem.getTitle());
5.在使用get()之前,使用containsKey()检查映射(checks a map with containsKey(), before using get())
This method checks for the presence of a key in a map using containsKey(), before attempting to fetch the value of the key using get(). This equates to doing two map lookups in a row. It is much simpler to just fetch the value with get, and checking for non null instead.
此方法使用containsKey()检查映射中是否存在键,然后尝试使用get()获取键的值。这相当于在一行中执行两次映射查找。只需使用get获取值,并检查非空值就简单多了。
As an example, instead of using
java">Map myMap = getSomeMap();
if (myMap.containsKey("foo")) {
String value = myMap.get("foo");
....
}
convert this to
java">Map myMap = getSomeMap();
String value = myMap.get("foo");
if (value != null) {
....
}
6.以次优方式按条件排序表达式(orders expressions in a conditional in a sub optimal way)
例如,此方法在if或while语句中构建条件表达式,其中表达式包含简单的局部变量比较和方法调用的比较。表达式对这些进行排序,以便方法调用先于简单的局部变量比较。这会导致方法调用在不需要的情况下执行,因此可能会导致大量代码白白执行。通过对表达式进行排序,使包含局部变量条件的简单条件优先,可以消除这种浪费。这假设方法调用没有副作用。如果这些方法确实有副作用,那么最好将这些调用从条件中取出并首先执行它们,并将值分配给局部变量。通过这种方式,您可以暗示呼叫可能会产生副作用。
This method builds a conditional expression, for example, in an if or while statement, where the expressions contain both simple local variable comparisons and comparisons on method calls. The expression orders these so that the method calls come before the simple local variable comparisons. This causes method calls to be executed in conditions when they do not need to be, and thus potentially causes a lot of code to be executed for nothing. By ordering the expressions so that the simple conditions containing local variable conditions are first, you eliminate this waste. This assumes that the method calls do not have side effects. If the methods do have side effects, it is probably a better idea to pull these calls out of the condition and execute them first, assigning a value to a local variable. In this way you give a hint that the call may have side effects.
Example:
java">if ((calculateHaltingProbability() > 0) && shouldCalcHalting) { }
would be better as
java">if (shouldCalcHalting && (calculateHaltingProbability() > 0) { }
Map、List设置默认初始值大小(涉及性能问题)
方法使用默认构造函数分配集合,即使事先知道(或至少可以合理猜测)集合中将放置多少项,因此不必要地导致集合的中间重新分配。
可以使用具有初始大小的构造函数,这会更好,但由于“贴图和集”的loadFactor,即使这也不是正确的估计。
如果您使用的是Guava,请使用它的方法分配具有预定大小的地图和集合,以获得不重新分配的最佳机会,例如:
java">Sets.newHashSetWithExpectedSize(int)
Maps.newHashMapWithExpectedSize(int)
如果不是,一个好的估计值是expectedSize/{LOADING_FACTOR},默认值为0.75
注意:HashMap扩容时,(数据大小 >= 初始化容器的大小的是(默认值16) * 0.75 会进行refresh操作以及数据的移动,影响性能
7.map遍历
例子:
java"> Map<String, String> map = new HashMap<>();
for (String key : map.keySet()) {
...
}
最好使用entrySet遍历
java"> for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
}
PS:后期遇到新的问题持续更新。。。