Sonar代码扫描常见规则总结

Sonar代码扫描常见规则

最近公司项目交付,交付前集成,功能,性能,安全种种测试工作就来了,由于测试离职,被抓壮丁,兼职起测试修改工作。小公司,平时敲(ctrl+c)代码(ctrl+v)
时,同事也不在意一些代码规范,以及一些常见的规约要求(阿里规约),所以代码扫描一地bug,漏洞,以及坏味道,道人委实因为这恨加了几天班。(心疼道人3秒)

因此,如果项目交付需要进行代码质量扫描等工作,一定要将代码规范写进公司代码规范中,并严格遵守。

程序员啦,代码提交时,idea编辑工具的话,可以使用sonarLine插件进行代码扫描,并修改扫描出的问题,再进行提交;或者使用阿里规约进行代码检测(至于sonar Rule 设置,后续博文会进行更新),下面是平时代码中常见的一些问题,希望对各位道友有所帮助。


注:括号中为sonar扫描规则

(1)非空判断(Nullcheck of value previously dereferenced)

错误代码

List> rows 
= (List>) dao.pagedQuery(sqlKey, param, pageIndex,
                    pageSize);
Map map = new HashMap();
int fileId = -1;
// for循环中 未做rows的非null判断
for (Map item : rows) {
    map.clear();
    ...
}

修改方案

...
if (rows != null && !rows.isEmpty()) {
    for (Map item : rows) {
        map.clear();
        ...
    }
}

(2) Map集合迭代时,采用EntrySet迭代器而不是KeySet迭代器【性能因素】(Inefficient use of keySet iterator instead of entrySet iterator)

错误代码(KeySet迭代器)

Map param = new HashMap<>();
//开始循环 
for (String key : param.keySet()) {
    list.add(new BasicNameValuePair(key, param.get(key)));
}

修改方案(EntrySet迭代器)

Map param = new HashMap<>()
//请求参数转换
for (Map.Entry entry : param.entrySet()) {
    list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}

(3)日志记录使用日志框架(log4j)(User a logger to log exception)

错误示例

try{
...
} catch (Exception e) {
    e.printStackTrace();
}

修改为

private static Logger logger = Logger.getLogger(FileTransferService.class);
...
try{
...
} catch (Exception e) {
    logger.error("getSetFileTransferObjectClass is Error!", e);
}

(4) 不需要使用封装类来定义布尔类型常量 (method needlessly boxes a boolean constant)

// 不推荐(涉及数据的自动装箱、拆箱)
Boolean b = true;
--------------------
// 推荐写法
boolean b = true;
// 或者 
Boolean b = Boolean.TRUE;

(5)字节数组或字符串编码转化时,需要指定编码格式(Method encodes String bytes without specifying the character encoding)

// 推荐写法
String string2 = new String(string1.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)); 
// 或者
String string3 = new String(string1.getBytes(), StandardCharsets.UTF_8));

byte[] data = string3.getBytes(StandardCharsets.UTF_8);

(6) StringBuffer或StringBuilder字符串拼接时,传递简单的连接字符串(Method passes simple concatenating string in StringBuffer or StringBuilder append)

不推荐写法

StringBuilder columnStr = new StringBuilder();
List> list = tableMap.get(key);
for (Map map : list) {
    columnStr.append(StringUtil.convertToString(map.get("COLUMN")) + ",");    
}

推荐写法

StringBuilder columnStr = new StringBuilder();
List> list = tableMap.get(key);
for (Map map : list) {
    columnStr.append(StringUtil.convertToString(map.get("COLUMN"))); 
    columnStr.append(",");
}

(7)split()函数特殊字符问题("." or “|” used for regular expression)

java中split()特殊符号"." “|” “*” “” “]”

- 关于点的问题是用string.split("[.]") 解决。
- 关于点的问题是用string.split("\\.") 解决。
- 关于竖线的问题用 string.split("\\|")解决。
- 关于星号的问题用 string.split("\\*")解决。
- 关于斜线的问题用 sring.split("\\\\")解决。
- 关于中括号的问题用 sring.split("\\[\\]")解决。

(8)魔数问题(坏味道)
0,1;“0”,“1” 其余所有变量引用,或者直接使用该变量都不符合Sonar的代码规范规则。

代码示例

// 不推荐的写法
if("old".equals(type)){
    ...
}
// 推荐写法
String oldIndex = "old";
if (oldIndex.equals(type)){
    ...
}

(9) Map,List等常用容器初始化需设置初始化大小(性能问题)

原因:以HashMap和ArrayList为例:

  • HashMap 扩容时(数据大小 >= 初始化容器大小【默认16】 * 负载因子【0.75】),
    会进行数据的rehash,和数据的移动影响性能。
  • ArrayList 扩容时,会进行数组大小(1.5倍)扩增;涉及到数组中元素的复制,然后copy
    到新的数组中。 复制影响性能,根据业务减少扩容次数。

注意事项:HashMap 的初始化大小必须是2的次幂(原因是:HashMap的hash算法与扩容机制【数据平移】决定)。

// 不推荐写法
Map pMap = new HashMap<>();
// 推荐写法
Map pMap = new HashMap<>(32);

Sonar代码扫描常见规则总结_第1张图片

你可能感兴趣的:(代码整洁之道)