Sonar代碼掃描常見規則總結

Sonar代碼掃描常見規則

最近公司項目交付,交付前集成,功能,性能,安全種種測試工作就來了,由於測試離職,被抓壯丁,兼職起測試修改工作。小公司,平時敲(ctrl+c)代碼(ctrl+v)
時,同事也不在意一些代碼規範,以及一些常見的規約要求(阿里規約),所以代碼掃描一地bug,漏洞,以及壞味道,道人委實因爲這恨加了幾天班。(心疼道人3秒)

因此,如果項目交付需要進行代碼質量掃描等工作,一定要將代碼規範寫進公司代碼規範中,並嚴格遵守。

程序員啦,代碼提交時,idea編輯工具的話,可以使用sonarLine插件進行代碼掃描,並修改掃描出的問題,再進行提交;或者使用阿里規約進行代碼檢測(至於sonar Rule 設置,後續博文會進行更新),下面是平時代碼中常見的一些問題,希望對各位道友有所幫助。


注:括號中爲sonar掃描規則

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

錯誤代碼

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

修改方案

...
if (rows != null && !rows.isEmpty()) {
    for (Map<String, Object> item : rows) {
        map.clear();
        ...
    }
}

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

錯誤代碼(KeySet迭代器)

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

修改方案(EntrySet迭代器)

Map<String, String> param = new HashMap<>()
//請求參數轉換
for (Map.Entry<String, String> 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<Map<String, String>> list = tableMap.get(key);
for (Map<String, Object> map : list) {
    columnStr.append(StringUtil.convertToString(map.get("COLUMN")) + ",");    
}

推薦寫法

StringBuilder columnStr = new StringBuilder();
List<Map<String, String>> list = tableMap.get(key);
for (Map<String, Object> 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<String, String> pMap = new HashMap<>();
// 推薦寫法
Map<String, String> pMap = new HashMap<>(32);

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章