Sonar代碼掃描常見問題


Use try-with-resources or close this "BufferedOutputStream" in a "finally" clause.

參考:https://blog.csdn.net/libusi001/article/details/103848922

解決方法: 在finally中關閉FileInputStream,主要是關閉方式不對,finally代碼塊中,應該要對每個stream進行單獨關閉,而不能統一寫在一個try-catch代碼中。

A NullPointerException might be thrown as ‘XXX’ is nullable here.

空指針,解決方式:先判斷或者先實例化,再訪問里面的屬性或者成員。

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;

Cast one of the operands of this multiplication operation to a “long”

說明:int數運算最終再把結果轉為long將有可能產生溢出
解決方案:轉換為long型預算

舉例:
long bigNum = Integer.MAX_VALUE + 2; // Noncompliant. Yields -2147483647

換為
long bigNum = Integer.MAX_VALUE + 2L;

Close this “XXX”.

說明:流沒有顯示的關閉。
解決方案:在fianlly語句塊內關閉。

Remove or correct this useless self-assignment.

說明:缺少this
解決方案:用this.xxx=xxx來替代
舉例:
public void setName(String name) {
name = name;
}

換為
public void setName(String name) {
this.name = name;
}

Correct this “&” to “&&”.

說明:錯誤的使用&和&&
解決方案:根據情況使用&和&&

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 語句判斷條件重復
解決方案:去掉多余的判斷條件

Make this “XXX” field final.

說明:將某個字段置為final,常見在Exception的參數
解決方案:將字段置為final

Remove this call to “equals”; comparisons between unrelated types always return false.

說明:去掉equals判斷語句,因為總為false
解決方案:去掉equals語句

Remove this return statement from this finally block.

說明:在finally語句塊中有return語句
解決方案:去掉finally語句塊的return語句或者放在finally語句塊之外

Remove this continue statement from this finally block.

說明:在finally語句塊中有continue語句
解決方案:去掉finally語句塊中的continue語句或者放在finally語句塊之外

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
// …
}

Add a type test to this method.

說明:強轉前未判斷類型
解決方案:強轉前先判斷類型

舉例:
ErpVO ev = (ErpVO) obj;
return this.userCode.equals(ev.getUserCode());

換為
if (obj == null) {
return false;

}

if (obj.getClass() != this.getClass()) {
return false;

}

Add an end condition to this loop.

說明:沒有退出條件

解決方案:根據情況來決定方法的退出條件

Make “XXX” an instance variable.

說明:有些類不是線程安全的,將變量生命為靜態的可能會導致線程安全問題
解決方案:將變量聲明為實例的。

Strings and Boxed types should be compared using "equals()"

字符串和包裝類型對比時應該使用equals方法。

解釋
使用引用相等==或!=比較java.lang.String或包裝類型(如java.lang.Integer)的兩個實例幾乎總是false,因為它不是在比較實際值,而是在內存中的位置(地址)。

在Java 中包裝類型與基本數據類型存儲位置不同。

  • Java 基本數據類型存放位置
    方法參數、局部變量存放在棧內存中的棧楨中的局部變量表
    常量存放在常量池中

  • 包裝類型如Integer存放位置
    常量池
    堆內存

Integer 存儲在常量池中時可以使用對比,但當在堆內存中時,使用對比,實際對比的是兩個內存地址而非值。

Reduce the number of conditional operators (4) used in the expression (maximum allowed 3)

在一個表達式中條件判斷不應該超過三個

//修改前
boolean rollback = (receiveType == Constants.ONE || receiveType == Constants.TWO || receiveType == Constants.THREE) && (result == null || !result.isSuccess());

//修改后,提取成一個方法
boolean rollback = checkReceiveType(receiveType) && (result == null || !result.isSuccess());

private boolean checkReceiveType(int receiveType) {
        return receiveType == Constants.ONE || receiveType == Constants.TWO || receiveType == Constants.THREE;
    }

The Cyclomatic Complexity of this method "xxx" is 19 which is greater than 15 authorized.

代碼的復雜度太高了,通常可以把代碼中獨立的業務邏輯抽取成單獨的方法;
sonar掃描是按照一個條件判斷算一個復雜度的,也就是說在一個方法中不要寫超過15個條件判斷;
靈活使用StringUtils.isAnyBlank/isNoneBlank/BooleanUtils.and/BooleanUtils.or可以把多個條件判斷變成一個

//修改前
if(this.acId== null||this.userId==null||!Md5Util.encrypt(inputSign).equals(this.getMd5Sign())){
                flag = false;
            }
//修改后
if(StringUtils.isAnyBlank(this.acId,this.userId)||!Md5Util.encrypt(inputSign).equals(this.getMd5Sign())){
                flag = false;
            }

Return an empty collection instead of null

不能直接返回null

//修改前
return null

//修改后
return Collections.emptyList()/Collections.EmptyMap/Collections.EmptySet/new String[0]

Refactor this code to not nest more than 5 if/for/while/switch/try statements.

if/for/while/switch/try嵌套不能超過5層

Iterate over the "entrySet" instead of the "keySet"

遍歷map時,使用entrySet,而不是keySet;

解釋
"entrySet()" should be iterated when both the key and value are needed;
通過查看源代碼發現,調用方法keySetMap.keySet()會生成KeyIterator迭代器,其next方法只返回其key值,而調用entrySetMap.entrySet()方法會生成EntryIterator 迭代器,其next方法返回一個Entry對象的一個實例,其中包含key和value。
所以當我們用到key和value時,用entrySet迭代性能更高

Use "Integer.parseInt" for this string-to-int conversion

使用Integer.parseInt 代替 Integer.valueOf

解釋
Integer.parseInt(s)是把字符串解析成int基本類型,
Integer.valueOf(s)是把字符串解析成Integer對象類型

Replace "Collections.EMPTY_LIST" by "Collections.emptyList()

Collections.EMPTY_LIST VS Collections.emptyList()
Collections. emptyList()返回的也是一個空的List,它與Collections.EMPTY_LIST的唯一區別是,Collections. emptyList()支持泛型,所以在需要泛型的時候,可以使用Collections. emptyList()。
注意,這個空的集合是不能調用add來添加元素的,會直接拋異常

為啥不直接new ArrayList()呢?
因為new ArrayList()在初始化時會占用一定的資源

————————————————
參考:
https://blog.csdn.net/asdasd3418/article/details/83791630/
https://www.jianshu.com/p/f67a6f18e066


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM