目录
1、Introduce a new variable instead of reusing the parameter "prefixKey"
2、Remove the boxing to "Double"; The argument is already of the same type.
3、A “NullPointerException” could be thrown; “document” is nullable here.
4、Remove this conditional structure or edit its code blocks so that they’re not all the same.
5、Change this condition so that it does not always evaluate to “false”
6、Cast one of the operands of this multiplication operation to a "long"
7、Use a “double” or “BigDecimal” instead.
8、Close this “XXX”.
9、Correct this “&” to “&&”.
10、This branch can not be reached because the condition duplicates a previous condition in the same sequence of “if/else if” statements
11、Make this “XXX” field final.
13、Remove this return statement from this finally block.
14、Remove this continue statement from this finally block.
15、Equality tests should not be made with floating point values.
16、Add a type test to this method.
17、Add an end condition to this loop.
18、Make “XXX” an instance variable.
19、Save and re-use this "Random"
20、The return value of “replace” must be used.
21、Unlock this lock along all executions paths of this method
22、Do something with the “boolean” value retyrbed by "xxx"
23、Either re-interrupt this method or rethrow the “InterruptedException” thar4t can be caught here.
24、Use the original value instead
25、Update this method so that its implementation is not identical to "delete" on line 71
26、Define and throw a dedicated exception instead of using a generic one.
27、Complete the task associated to this TODO comment.
28、immediately return this expression instead of assigning it to the temporary variable "swapStream"
29、remove the declaration of thrown exception 'org.hibernate.exception.DataException' which is a runtime exception
30、Rename this local variable name to match the regular expression '^[a-z][a-zA-Z0-9]*$'
31、Define a constant instead of duplicating this literal “XXXX” 4 times.
32、Refactor this method to reduce its Cognitive Complexity from 55 to the 15 allowed.
1、Introduce a new variable instead of reusing the parameter "prefixKey"
不要用传递过来的参数去重新赋值做判断等
可以新建一个参数 等于传递过来的参数 用新的参数去操作
private String getBatchSaveKey(Map<String, String> map, String prefixKey, String... keys) {undefined
//创建一个newPrefixKey
String newPrefixKey;
newPrefixKey = prefixKey.endsWith(RedisKeys.DELIMITER) ? prefixKey.substring(0, prefixKey.length() - 1) : prefixKey;
if (keys.length == 0) {undefined
return newPrefixKey;
}
不直接用prefixKey = prefixKey.endsWith(RedisKeys.DELIMITER) ? prefi。。。
也不直接用return prefixKey;而是去创建newPrefixKey
2、Remove the boxing to "Double"; The argument is already of the same type.
移除装箱转换Double类型,这个参数已经是一样的类型了。
Boolean.valueOf //装箱
(Boolean) //装箱
Boolean.valueOf((Boolean) val) //两次装箱,多此一举
重复转换,删除即可。
3、A “NullPointerException” could be thrown; “document” is nullable here.
这种提示是指可能存在空指针异常,需要增加空值检测。
说明:未做非空校验,可能产生空指针
解决方案:加上非空校验
解决方式:先判断或者先实例化,再访问里面的属性或者成员。
4、Remove this conditional structure or edit its code blocks so that they’re not all the same.
写if else的时候,卡条件卡得离散了一点,本身可以合成一个的,结果写成了多级if,增加了程序的复杂度。
例子:
if(i > 0){
return i;
}else{
#### return i;
}
删除此条件结构或编辑其代码块,使它们不完全相同。
因为返回的结果都一样,需要去掉筛选分支。
5、Change this condition so that it does not always evaluate to “false”
条件判断后一直返回的结果为false。需要改条件判断。
6、Cast one of the operands of this multiplication operation to a "long"
需要强转类型
例如转成long
(long)Integer.MaxValue;
说明:int数运算最终再把结果转为long将有可能产生溢出
解决方案:转换为long型预算
举例:
long bigNum = Integer.MAX_VALUE + 2; // Noncompliant. Yields -2147483647
换为
long bigNum = Integer.MAX_VALUE + 2L;
7、Use a “double” or “BigDecimal” instead.
说明:两个float计算会产生不精确的结果
解决方案:将float换为double或者BigDecimal计算
举例:
float a = 16777216.0f;
float b = 1.0f;
float c = a + b; // Noncompliant; yields 1.6777216E7 not 1.6777217E7
double d = a + b; // Noncompliant; addition is still between 2 floats
换为
float a = 16777216.0f;
float b = 1.0f;
BigDecimal c = BigDecimal.valueOf(a).add(BigDecimal.valueOf(b));
double d = (double)a + (double)b;
8、Close this “XXX”.
说明:流没有显示的关闭。
解决方案:在fianlly语句块内关闭。
Remove or correct this useless self-assignment.
说明:缺少this
解决方案:用this.xxx=xxx来替代
举例:
public void setName(String name) {undefined
name = name;
}
换为
public void setName(String name) {undefined
this.name = name;
}
9、Correct this “&” to “&&”.
说明:错误的使用&和&&
解决方案:根据情况使用&和&&
10、This branch can not be reached because the condition duplicates a previous condition in the same sequence of “if/else if” statements
说明:if else if 语句判断条件重复
解决方案:去掉多余的判断条件
11、Make this “XXX” field final.
说明:将某个字段置为final,常见在Exception的参数
解决方案:将字段置为final
12、Remove this call to “equals”; comparisons between unrelated types always return false.
说明:去掉equals判断语句,因为总为false
解决方案:去掉equals语句
13、Remove this return statement from this finally block.
说明:在finally语句块中有return语句
解决方案:去掉finally语句块的return语句或者放在finally语句块之外
14、Remove this continue statement from this finally block.
说明:在finally语句块中有continue语句
解决方案:去掉finally语句块中的continue语句或者放在finally语句块之外
15、Equality tests should not be made with floating point values.
说明:浮点数之间用 == 来比较大小不准确
解决方案:用Number或者BigDecimal来比较
举例:
float myNumber = 3.146;
if ( myNumber == 3.146f ) { //Noncompliant. Because of floating point imprecision, this will be false
// …
}
if ( myNumber != 3.146f ) { //Noncompliant. Because of floating point imprecision, this will be true
// …
}
16、Add a type test to this method.
说明:强转前未判断类型
解决方案:强转前先判断类型
举例:
ErpVO ev = (ErpVO) obj;
return this.userCode.equals(ev.getUserCode());
换为
if (obj == null) {undefined
return false;
}
if (obj.getClass() != this.getClass()) {undefined
return false;
}
…
17、Add an end condition to this loop.
说明:没有退出条件
解决方案:根据情况来决定方法的退出条件
18、Make “XXX” an instance variable.
说明:有些类不是线程安全的,将变量生命为静态的可能会导致线程安全问题
解决方案:将变量声明为实例的。
19、Save and re-use this "Random"
"Random" objects should be reused 创建的随机数不安全。
解决方案
1、sonar建议:
private Random rand = SecureRandom.getInstanceStrong(); // SecureRandom is preferred to Random public void doSomethingCommon() {
int rValue = this.rand.nextInt(); //...
}
2、SecureRandom random = new SecureRandom();
20、The return value of “replace” must be used.
String s = "2,2";
s.replace("2", "3");
需要代替,s字符串并未改变;
或者 直接拼接s.replace("2", "3");
21、Unlock this lock along all executions paths of this method
需要解锁 lock.unlock();
22、Do something with the “boolean” value retyrbed by "xxx"
解决:
public boolean doSome(){
}
if(!doSome){
......
}
如果返回boolean ,需要判断为false的情况;用!()判断 失败情况。
23、Either re-interrupt this method or rethrow the “InterruptedException” thar4t can be caught here.
解决:
try(){
}catch (InterruptedException e){
//抛出InterruptedException 异常需要重新清除线程的中断状态,添加如下
Thread.currentThread().interrupt();
}
24、Use the original value instead
例子:
public int compare(eq22 e) {
return -this.getCode1().compareTo(this.getCode2());
}
用了compareTo方法,取反的话,就算是正数取反,结果将是不可靠的。
解决:
public int compare(eq22 e) {
return -1 * value;
}
25、Update this method so that its implementation is not identical to "delete" on line 71
更新此方法,以便其执行是不相同的"delete"71行。
解决:
两个方法的内容完全一致,不用写两遍,在其中一个方法中调用另一个方法即可。或者删掉一个,全部使用另一个方法
26、Define and throw a dedicated exception instead of using a generic one.
定义并抛出一个专用的异常来代替一个通用的异常。
解决方法:不要直接抛Error,RuntimeException/Throwable/Exception这样的通用的异常,使用更具体的异常代替
比较常用的 IllegalArgumentException(不合法参数的异常) 。
其他的还有 IOException等
示例如下:
throw new IllegalArgumentException("invalid argument, please check argument.");
27、Complete the task associated to this TODO comment.
问题分析:
TODO标记通常用于标记需要更多代码但开发人员希望稍后实现的地方。
有时开发人员没有时间,或者只是忘记返回到该标记。
此规则旨在跟踪这些标记,并确保它们不会被忽略。
解决:
将TODO的内容完善、说明类、方法是干什么的。
28、immediately return this expression instead of assigning it to the temporary variable "swapStream"
立即返回此表达式而不是将其分配给临时变量"swapStream"
问题分析:
声明一个变量只是为了立即返回或抛出它是一种不好的做法。
一些开发人员认为,这种做法提高了代码的可读性,因为它使他们能够显式地命名返回的内容。
但是,此变量是一个内部实现细节,不会向方法的调用方公开。方法名称应足以让调用方确切知道将返回什么。
解决:
直接return new ByteArrayInputStream(baos.toByteArray());,而不是定义一个swapStream接收,然后返回swapStream。
return new ByteArrayInputStream(baos.toByteArray());
29、remove the declaration of thrown exception 'org.hibernate.exception.DataException' which is a runtime exception
解决:删除抛出异常的声明,dataException是一个运行时异常
30、Rename this local variable name to match the regular expression '^[a-z][a-zA-Z0-9]*$'
方法名需要遵守命名规则
不合规
public void doSomething(int my_param) {
int LOCAL;
...
}
合规:
public void doSomething(int myParam) {
int local;
...
}
31、Define a constant instead of duplicating this literal “XXXX” 4 times.
类似这种,当一个不变的字符串在一个文件中多次出现,就应该给这些字符串提取成常量,
这样方便以后修改和维护。但是说实话提取常量这个异味真的很枯燥,并且代码中有大量的这种情况,
感觉每个项目或者每个模块都应该提取一个常量类,这样这个模块用到这些不变字符串,
就直接从这个类中获取,但是这个工作量有点大哈哈,我就简单的尝试了一下,把自定义报表那部分提取常量,但是进行了一部分就没有进行下去了,枯燥且工作量大
但是我觉得这个工作还是做比较好,这样便于以后的维护,常量值改变只用改一个地方就好了,不用所有地方都修改。
32、Refactor this method to reduce its Cognitive Complexity from 55 to the 15 allowed.
关于代码圈复杂度大于15的异味,以及代码过长的异味,说实话也没有什么好的方法,只能读代码,然后抽离函数出来,当然抽离函数不可能一次就能做到代码简洁之道要求的那样,一个函数只做一件事,单一层次原则。但是我们也不能因为做不到这样就就什么都不做,还是要迈出这一步,先抽离函数,虽然没有做到单一层次原则,但是消除了异味。下面代码是对上面的进行简单的函数抽离,消除异味
=======================================
Avoid long parameter lists. | 方法参数过多,最多允许5个 |
Missing a Javadoc comment. | 需要注释 |
Expected @param tag for 'area'. | 需要注释 |
Expected @return tag. | 需要注释 |
Expected @throws tag for 'Exception'. | 需要注释 |
Unused @param tag for 'licenseInfoMap'. | 修改注释 |
Line is longer than 160 characters (found 162). | 每一行代码不得超过160个字符,需要分行 |
Add a private constructor to hide the implicit public one. | 常量类和工具类需要一个私有的构造器,同时将该类定义为final,不可继承 |
Variables that are final and static should be all capitals, 'logger' is not all capitals. | final修饰的变量名称需要全部大写 |
Only variables that are final should contain capitals (except for underscores in standard prefix/suffix), '_tar' is not final. | 只有final修饰的变量名称中才可以有下划线,要么去掉下划线,要么加上final修饰符,Map,List和java对象加上final修饰符后,代表这个对象指向的内存地址不可变,但内容和值都是可以改变的 |
Name '_targetDataSources' must match pattern '(^[a-z][a-z0-9][a-zA-Z0-9]{0,50}$)'. | 变量命名需要符合正则表达式 |
The field name indicates a constant but its modifiers do not | 变量没有final修饰却使用了final变量的命名规则 |
Variables should start with a lowercase character, 'SUSPEND_MAP' starts with uppercase character. | 普通变量(即没有final修饰)需要驼峰式命名,首字母为小写 |
More than 8 parameters (found 9). | 构造方法只能有7个参数 |
Constructor has 9 parameters, which is greater than 7 authorized. | 构造方法只能有7个参数 |
Define a constant instead of duplicating this literal "muluList" 6 times. | 某个字符串出现了4次或以上,需要定义一个常量来代替 |
A method/constructor shouldnt explicitly throw java.lang.Exception | 不能直接抛出Exception,需要精确到具体的异常,且最多抛出4个,超过请try catch |
Define and throw a dedicated exception instead of using a generic one. | 不能直接抛出Exception,需要精确到具体的异常,且最多抛出4个,超过请try catch |
Remove this useless assignment to local variable "orgnIdL". | 一个没有使用的变量,删掉即可 |
Avoid unused private fields such as 'fastGroup'. | 一个没有使用的变量,删掉即可。如果不能删,则将private改为protected或default即可。 |
Exceptional return value of java.io.File.mkdirs() ignored in ... | mkdirs方法有返回值,如果是false则代表文件夹创建失败,需要处理。判断返回值是否正确,并进行处理,如记日志或抛异常等 |
Exceptional return value of java.io.File.delete() ignored in ... | delete方法有返回值,如果是false则代表文件删除失败,需要处理。判断返回值是否正确,并进行处理,如记日志或抛异常等 |
Use "java.nio.Files#delete" here for better messages on error conditions. | 使用Files.delete(file.toPath())来代替file.delete() |
Suspicious comparison of a Integer reference to constant in ... | Integer需要使用equals来比较,这是由于超出(-128~127)范围后,==无法比较,但equals性能较低 |
Refactor the code in order to not assign to this loop counter from within the loop body. | 不要在循环体内操作计数器,重构代码 |
Rename "jdbcTemplate" which hides the field declared at line 116. | 一个类中变量名称重复,重命名变量名称即可 |
Field ssoServer has the same name as a method | 一个类中字段名称和方法名称重复,重命名即可 |
Merge this if statement with the enclosing one. | 多个if可以合并,合并成一个 |
Replace the synchronized class "StringBuffer" by an unsynchronized one such as "StringBuilder". | StringBuffer需要换成StringBuilder |
A "NullPointerException" could be thrown; "dataResults" is nullable here. | 在使用对象之前需要对这个对象进行非空判断 |
Possible null pointer dereference of track in ... | 在使用对象之前需要对这个对象进行非空判断 |
Update this method so that its implementation is not identical to "getDvStatus" on line 149. | 两个方法的内容完全一致,不用写两遍,在其中一个方法中调用另一个方法即可。或者删掉一个,全部使用另一个方法 |
Add a nested comment explaining why this method is empty, throw an UnsupportedOperationException or complete the implementation. | 空的方法体内部需要写一个注释 |
Avoid throwing raw exception types. | 自定义一个异常来继承RuntimeException,然后抛出这个自定义的异常,而不是抛出通用的RuntimeException |
Define and throw a dedicated exception instead of using a generic one. | 自定义一个异常来继承RuntimeException,然后抛出这个自定义的异常,而不是抛出通用的RuntimeException |
New exception is thrown in catch block, original stack trace may be lost | 在catch中抛出异常会使抛出的异常混淆,所以抛出的异常必须带着原异常信息。例如:throw new BusinessException(errorMsg, e)这里第二个参数是必须的 |
Avoid empty catch blocks | catch代码块不能为空 |
Either remove or fill this block of code. | 删掉或填充这个代码块 |
Return an empty collection instead of null. | 返回空集合Collections.emptyList()而不是null |
Put single-quotes around '-' to use the faster "indexOf(char)" method. | 将双引号改为单引号,理由是用char来找字符比用String来找效率更高 |
Method length is 221 lines (max allowed is 200). | 一个方法最多200行,试着压缩,实在不行只能拆成多个方法 |
Avoid printStackTrace(); use a logger call instead. | catch中使用logger.error来代替e.printStackTrace()。Logger logger = LoggerFactory.getLogger(this.getClass())。记住,logger不可以在数据库对象类中使用 |
Remove this expression which always evaluates to "true" | 这个判断语句总是为true,删掉即可 |
... concatenates strings using + in a loop | 在循环中String不要用加号来拼接,而是使用StringBuilder |
Avoid using implementation types like 'LinkedHashMap'; use the interface instead | 在方法的参数中不要使用具体的实现类对象,而是使用它的接口对象。例如:不用LinkedHashMap而用Map |
Iterate over the "entrySet" instead of the "keySet". | 遍历Map不使用keySet而使用entrySet |
... makes inefficient use of keySet iterator instead of entrySet iterator | 遍历Map不使用keySet而使用entrySet |
Move constants to a class or enum. | 接口中不要定义常量,移到常量类中 |
Boxing/unboxing to parse a primitive ... | 使用parse方法来代替valueOf方法 |
Null passed for non-null parameter of ... | 将一个可能为空的参数传到了一个方法中,但在该方法中,该参数不可为空。修改这个方法,在使用变量前进行非空判断,则这个参数就成为了可为空参数 |
Remove this "Integer" constructor | 不要使用new Integer来初始化变量的值,使用Integer.valueOf |
new com.model.CatalogInfo() invokes inefficient new Integer(int) constructor; use Integer.valueOf(int) instead | 不要使用new Integer来初始化变量的值,使用Integer.valueOf |
HTTP parameter directly written to HTTP header output in ... | resp.setHeader("Content-Disposition", "attachment;filename = " + fileName)改为resp.setHeader("Content-Disposition", "attachment;filename = " + new String(fileName.getBytes("GBK"), "ISO8859-1")) |
Relative path traversal in ... | new File(filePath + fileName)改为new File(filePath, fileName)。还有使用new FileInputStream(File srcFile)而不是使用new FileInputStream(filePath + fileName) |
Boxing/unboxing to parse a primitive ... | .valueOf改为.parseXXX,这是由于valueOf返回的是包装类对象,而parseXXX返回的是值 |
Use try-with-resources or close this "FileInputStream" in a "finally" clause. | 使用try(FileInputStream inFile = new FileInputStream(file)){System.out.println("...")}catch{}且不需要finally代码块来关闭,这是jdk1.7的新写法,可以将一些可自动关闭的资源写在try()中,就可以直接实现自动关闭 |
Change this "try" to a try-with-resources. (sonar.java.source not set. Assuming 7 or greater.) | 使用try(FileInputStream inFile = new FileInputStream(file)){System.out.println("...")}catch{}且不需要finally代码块来关闭,这是jdk1.7的新写法,可以将一些可自动关闭的资源写在try()中,就可以直接实现自动关闭 |
Replace this use of System.out or System.err by a logger. | System.out换成logger.info。记住,logger不可以在数据库对象类中使用。 |
System.out.println is used | System.out换成logger.info。记住,logger不可以在数据库对象类中使用。 |
Variable 'auditTypeName' must be private and have accessor methods. | 只有静态变量才可以用public修饰,所以public改为private或protected或default |
The return value of "valueOf" must be used. | 这个语句的返回值必须要被使用,删掉或者使用它 |
Return value of String.valueOf(Object) ignored in ... | 这个语句的返回值必须要被使用,删掉或者使用它 |
Synchronize this method to match the synchronization on "setSuspendMap". | 一组get和set方法,如果其中一个方法被synchronized修饰,则另一个也需要使用synchronized 修饰 |
An empty statement (semicolon) not part of a loop | 双分号导致sonar认为两个分号之间有一个空语句,删掉一个分号即可 |
Avoid empty if statements | if代码块不能为空,删掉或填充代码 |
A class which only has private constructors should be final | 有private构造函数的类需定义为final类 |
Class Convert2Track should be declared as final. | 该类需定义为final类 |
Verify this is the key that was intended; it was already set before. | 该key之前已被塞入过一次,一个key塞两次没有意义,去掉一次 |
Extract this nested try block into a separate method. | 不要在try代码块中再次使用try,去掉内部的,或者把内部的try代码块拉到外面去 |
Absolute path traversal in ... | 直接将文件的绝对路径传到后台,然后生成File对象即会报错。如D:\1.jpg,不可直接传绝对路径,如果知道这个文件会在d盘,可定义常量D:\,然后传值为1.jpg,后台进行拼接后生成File对象即可 |
Only one statement per line allowed. | 每一行只允许一个语句,可能是多写了分号,去掉即可 |
Make this anonymous inner class a lambda (sonar.java.source not set. Assuming 8 or greater.) | jdk1.8之后推荐使用兰布达表达式。请参考:https://blog.csdn.net/qq_33865313/article/details/81203412 |
Non-virtual method call in ... passes null for non-null parameter of ... | 将一个可能为空的参数传到了一个方法中,但在该方法中,该参数不可为空。修改这个方法,在使用变量前进行非空判断,则这个参数就成为了可为空参数 |
A "NullPointerException" could be thrown; "printStream" is nullable here. | 可能会抛出空指针异常,先进行非空判断 |
... could be null and is guaranteed to be dereferenced in ... | 可能会抛出空指针异常,先进行非空判断 |
Unused import - ... | 引入了一个类,但是没有使用,删掉即可 |
2' is a magic number. | 这是一个魔术数字,需要定义一个常量,然后引用常量,而不是直接使用这个数字 |
+' is preceded with whitespace. | 代码之前不能有空格,删掉空格即可 |
;' is not followed by whitespace. | 代码之后没有空格,需要添加一个空格 |
?' is not preceded with whitespace. | 代码之前没有空格,需要添加一个空格 |
Redundant 'private' modifier. | 这个修饰符是多余的,删掉该修饰符即可 |
Incorrect lazy initialization of static field | 对静态变量的延迟初始化有问题。一般可以试着把static修饰符去掉,或者在静态代码块中进行static变量的初始化。 |
... Service not allowed Autowired field ... | Service中不允许自动注解Manager,一般Service中都是注解其他Service,删掉这个Manager,换成相同功能的Service |
Unread field: ... should this field be static? | final修饰的字段需要加上static修饰符 |
member def modifier' has incorrect indentation level 8, expected level should be 4. | 缩进不对,可以删掉前面的缩进,用Tab键缩进,或者MyEclipse用Ctrl+Shift+F格式化代码 |
Change this code to use a stronger protocol. | 修改编码以使用更强壮的协议,照着给的编码改就行 |
for child at indentation level 21 not at correct indentation, 20 | 首行缩进不对,使用Tab键进行缩进 |
0 is a valid index, but is ignored by this check. | 0是一个有效的值,但在这里不能用。一般都是要用特殊的值,比如indexOf应该使用>=0或>-1 |
Use already-defined constant '...' instead of duplicating its value here. | 使用已经定义的常量,而不是在这里复制它的值 |
Using the '.*' form of import should be avoided - ... | 不要使用.*的方式将所有类导入进来,而应该详细的导入每一个用到的类 |