Sonar 常用代碼規則(二)


摘要:幫助公司部署了一套sonar平台,經過一段時間運行,發現有一些問題出現頻率很高,因此有必要將這些問題進行整理總結和分析,避免再次出現類似問題。

作者原創技術文章,轉載請注明出處

===================================================================

id: 85 name:Broken Null Check  type:CODE SMELL  severity:CRITICAL  

Comment:The null check is broken since it will throw a Nullpointer itself. The reason is that a method is called on the object when it is null. It is likely that you used || instead of && or vice versa. <p> This rule is deprecated, use {rule:squid:S1697} instead. </p>  definition:null檢查是壞的,因為它將拋出一個Nullpointer本身。 原因是當對象為空時調用該方法。 很可能你使用|| 而不是&&,反之亦然。

advice: 不合規案例: if (str == null && str.length() == 0) { System.out.println("String is empty"); } if (str != null || str.length() > 0) { System.out.println("String is not empty"); } 合規案例: if (str == null || str.length() == 0) { System.out.println("String is empty"); } if (str != null && str.length() > 0) { System.out.println("String is not empty"); }

-------------------------------------------------------------------

id:123  name:Useless Operation On Immutable  type:CODE SMELL  severity:CRITICAL

Comment:An operation on an Immutable object (BigDecimal or BigInteger) won't change the object itself. The result of the operation is a new object. Therefore, ignoring the operation result is an error.

definition:示例代碼: import java.math.*; class Test { void method1() { BigDecimal bd=new BigDecimal(10); bd.add(new BigDecimal(5)); // 這里違背了規則 } void method2() { BigDecimal bd=new BigDecimal(10); bd = bd.add(new BigDecimal(5)); // 這里沒有違背規則 } }

advice: 對不可變對象(BigDecimal或BigInteger)的操作不會更改對象本身。 操作的結果是一個新的對象。 因此忽略操作結果是一個錯誤。

-------------------------------------------------------------------

id: 169 name:Empty Finally Block  type:CODE SMELL  severity:CRITICAL

Comment:<p> Avoid empty finally blocks - these can be deleted. </p> <p> This rule is deprecated, use {rule:squid:S00108} instead. </p>

definition:這些是可以刪掉的。不合規案例: for (int i = 0; i < 42; i++){} // Empty on purpose or missing piece of code ?

advice: 空的 finally 塊:避免空的 finally 塊

-------------------------------------------------------------------

id:  263 name:  type:  severity:  Comment: 

definition:使用equals()比較對象引用; 避免用==,或者 != 進行比較。  

advice: 

不合規案例:
String str1 = "blue";
String str2 = "blue";
String str3 = str1;

if (str1 == str2)
{
System.out.println("they're both 'blue'"); // this doesn't print because the objects are different
}

if (str1 == "blue")
{
System.out.println("they're both 'blue'"); // this doesn't print because the objects are different
}

if (str1 == str3)
{
System.out.println("they're the same object"); // this prints
}
合規案例:
String str1 = "blue";
String str2 = "blue";
String str3 = str1;

if (str1.equals(str2))
{
System.out.println("they're both 'blue'"); // this prints
}

if (str1.equals("blue"))
{
System.out.println("they're both 'blue'"); // this prints
}

if (str1 == str3)
{
System.out.println("they're the same object"); // this still prints, but it's probably not what you meant to do
}

-------------------------------------------------------------------

id: 264 name:  type:  severity:  Comment: 

definition:空的 Synchronized 塊:避免空的 synchronized 塊 - 它們是無用的

 advice: 不合規案例:

for (int i = 0; i < 42; i++){} // Empty on purpose or missing piece of code ?

-------------------------------------------------------------------

id:272  name:  type:  severity:  Comment: 

definition:  沒有經驗的程序員有時會混淆比較概念,並使用equals()來比較null值

advice: 

不合規案例:
interface KitchenTool { ... };
interface Plant {...}

public class Spatula implements KitchenTool { ... }
public class Tree implements Plant { ...}
//...
Spatula spatula = new Spatula();
KitchenTool tool = spatula;
KitchenTool [] tools = {tool};

Tree tree = new Tree();
Plant plant = tree;
Tree [] trees = {tree};

if (spatula.equals(tree)) { // Noncompliant; unrelated classes
// ...
}
else if (spatula.equals(plant)) { // Noncompliant; unrelated class and interface
// ...
}
else if (tool.equals(plant)) { // Noncompliant; unrelated interfaces
// ...
}
else if (tool.equals(tools)) { // Noncompliant; array & non-array
// ...
}
else if (trees.equals(tools)) { // Noncompliant; incompatible arrays
// ...
}
else if (tree.equals(null)) { // Noncompliant
// ...
}

-------------------------------------------------------------------

id: 796 name:  type:  severity:  Comment: 

definition:此方法調用notify()而不是notifyAll()

advice: Java監視器通常用於多個條件。 調用notify()只喚醒一個線程,這意味着線程喚醒可能不是等待調用者滿足的條件的線程。

-------------------------------------------------------------------

id:800  name:  type:  severity:  Comment: 

definition:此構造函數讀取尚未分配值的字段。 這通常是由程序員錯誤地使用該字段而不是構造函數的參數之一引起的。  

advice: 

此構造方法中使用了一個尚未賦值的字段或屬性。
String a;
public SA() {
String abc = a;
System.out.println(abc);
}

-------------------------------------------------------------------

id: 802 name:  type:  severity:  Comment: 

definition: 格式字符串定義錯誤 

advice: 例如:formatter.format("%<s %s", "a", "b"); 拋出MissingFormatArgumentException異常

-------------------------------------------------------------------

id:806  name:  type:  severity:  Comment: 

definition:此代碼創建一個異常(或錯誤)的對象,但不會用它做任何事情

advice: 

例如:if (x < 0)
new IllegalArgumentException("x must be nonnegative");
這可能是程序員的意圖拋出創建的異常:
if (x < 0)
throw new IllegalArgumentException("x must be nonnegative");

-------------------------------------------------------------------

id:811  name:  type:  severity:  Comment: 

definition:有一個語句或分支,如果執行保證在此時值為空,並且該值保證被取消引用(除了涉及運行時異常的轉發路徑之外)。

advice: 在正常的null判斷分支上,對象去除引用操作是受保護的不允許的

-------------------------------------------------------------------

id: 815 name:  type:  severity:  Comment: 

definition:"equals(Object o)"方法不能對參數o的類型做任何的假設。比較此對象與指定的對象。當且僅當該參數不為 null,並且是表示與此對象相同的類型的對象時,結果才為 true

advice: 

示例代碼:
public class Foo {
// some code
public void equals(Object o) {
Foo other = (Foo) o;
// the real equals code
}
}
原因:
當你在實現類的equals方法時,不應該對參數有任何的預先設定。如上代碼所寫,
則設定了參數o肯定是Foo類的一個對象.但是如果在函數調用時,參數o不是一個Foo類或其子類,
就會導致代碼會拋出一個ClassCastException。因此在實現equals方法,應該加一個判斷,如果參數o不是一個Foo類對象,則返回false。

-------------------------------------------------------------------

id: 824 name:  type:  severity:  Comment: 

definition:該代碼同步一個封裝的原始常量,例如一個Boolean類型。  

advice: 

private static Boolean inited = Boolean.FALSE;
...
synchronized(inited) {
if (!inited) {
init();
inited = Boolean.TRUE;
}
}
...
由於通常只存在兩個布爾對象,此代碼可能是同步的其他無關的代碼中相同的對象,這時會導致反應遲鈍和可能死鎖

-------------------------------------------------------------------

id: 827 name:  type:  severity:  Comment: 

definition:  可以為null的值存儲在已注釋為@Nonnull的字段中。

advice: 為一個已經聲明為不能為null值的屬性賦值為null

-------------------------------------------------------------------

id:831  name:  type:  severity:  Comment: 

definition: 調用具有可變數量參數的格式字符串方法,但傳遞的參數數與格式字符串中%占位符的數量不匹配。 這可能不是作者的意圖。 

advice: 錯誤用法 - 格式化字符串參數的數目與占位符不相等

-------------------------------------------------------------------

id: 844 name:  type:  severity:  Comment: 

definition:

某些異常控制路徑上的引用值為空,在此處將被解引用。 當執行代碼時,這可能會導致NullPointerException異常。 請注意,因為FindBugs目前不修剪不可行的異常路徑,這可能是一個錯誤的警告。
另請注意,FindBugs將switch語句的默認情況視為異常路徑,因為默認情況通常是不可行的。

advice: 在異常null值處理分支調用的方法上,可能存在對象去除引用操作

-------------------------------------------------------------------

id:846  name:  type:  severity:  Comment: 

definition: 沒有足夠的參數傳遞以滿足格式字符串中的占位符。 執行此語句時將發生運行時異常。

advice: String的format操作缺少必要的參數。

-------------------------------------------------------------------

id: 849 name:  type:  severity:  Comment: 

definition:該代碼將保證為非負的值與負常數或零進行比較。  

advice: 保證非負數和負數進行比較

-------------------------------------------------------------------

id: 855 name:  type:  severity:  Comment: 

definition:  hasNext()方法調用next()方法。

advice:  這幾乎肯定是錯誤的,因為hasNext()方法不應該改變迭代器的狀態,而下一個方法應該改變迭代器的狀態。

-------------------------------------------------------------------

id:856  name:  type:  severity:  Comment: 

definition: 該方法似乎在循環中使用連接構建一個String。 在每次迭代中,String將轉換為StringBuffer / StringBuilder,附加到並轉換為String。 這可以導致迭代次數中的二次成本,因為每個迭代中重新生成增長的字符串。

 advice: 

通過使用StringBuffer(或Java 1.5中的StringBuilder)可以獲得更好的性能。
例如:
// 不好的寫法
String s = "";
for (int i = 0; i < field.length; ++i) {
s = s + field[i];
}

//優化的寫法
StringBuffer buf = new StringBuffer();
for (int i = 0; i < field.length; ++i) {
buf.append(field[i]);
}
String s = buf.toString();

-------------------------------------------------------------------

id:857  name:  type:  severity:  Comment: 

definition:

格式字符串占位符與相應的參數不兼容。 例如System.out.println(“%d \ n”,“hello”);
%d占位符需要一個數字參數,但是卻傳遞一個字符串值。 執行此語句時將發生運行時異常。

 advice: 

錯誤使用參數類型來格式化字符串

-------------------------------------------------------------------

id:873  name:  type:  severity:  Comment: 

definition:

代碼在interned String上同步。

private static String LOCK =“LOCK”;
...
   synchronized(LOCK){...}
...

 advice: 

常量字符串被實體化並由JVM加載的所有其他類共享。 因此,這可能鎖定什么對象導致其他代碼也可能被鎖。 這可能導致阻塞和死鎖行為。

-------------------------------------------------------------------

id: 878 name:  type:  severity:  Comment:  definition: 按位添加有符號字節值。添加一個字節值和已知具有8個較低位清除的值。 在對值進行任何按位操作之前,從字節數組加載的值將被擴展為32位。 因此,如果b [0]包含值0xff,並且x最初為0,則代碼((x << 8)+ b [0])將對擴展0xff進行符號擴展,以獲得0xffffffff,從而給出值0xffffffff作為 結果。

 advice: 

將字節數組打包到int中的以下代碼是非常錯誤的:

int result = 0;
for(int i = 0; i < 4; i++)
result = ((result << 8) + b[i]);
需要改成如下:

int result = 0;
for(int i = 0; i < 4; i++)
result = ((result << 8) + (b[i] & 0xff));

-------------------------------------------------------------------

id:879  name:  type:  severity:  Comment: 

definition: 方法調用將null傳遞給非空參數。可能為null的值傳遞給非空方法參數。 

advice:  參數注釋為始終為非空值的參數,或者分析表明它始終被取消引用。

-------------------------------------------------------------------

id: 880 name:  type:  severity:  Comment: 

definition:此構造函數讀取尚未分配值的字段。 這通常是由程序員錯誤地使用該字段而不是構造函數的參數之一引起的。

advice: 

此構造方法中使用了一個尚未賦值的字段或屬性。例如:
String a;
public SA() {
String abc = a;
System.out.println(abc);
}

===================================================================

 

看完點個贊唄,難道想白嫖不成?更多內容請訪問微信公眾號 :三國測,掃碼關注喲!

 

感謝閱讀,作者原創技術文章,轉載請注明出處

 

附錄:參考文獻&參考文章

Java代碼規范小結(一):http://www.jianshu.com/p/b50f01eeba4d

FindBugs Report安全代碼檢查工具問題解析:http://blog.csdn.net/wwbmyos/article/details/50549650

FindBugs規則整理(轉載):http://blog.csdn.net/hufang_lele/article/details/47090215

詳解FindBugs的各項檢測器:http://blog.csdn.net/yang1982_0907/article/details/18606171

其他推薦相關閱讀:

 

單元測試系列之一:如何使用JUnit、JaCoCo和EclEmma提高單元測試覆蓋率

 

測試系列之二:Mock工具Jmockit實戰

 

單元測試系列之三:JUnit單元測試規范

 

單元測試系列之四:Sonar平台中項目主要指標以及代碼壞味道詳解

 

單元測試系列之五:Mock工具之Mockito實戰

 

單元測試系列之六:JUnit5 技術前瞻

 

單元測試系列之七:Sonar 數據庫表關系整理一(rule相關)

 

單元測試系列之八:Sonar 數據庫表關系整理一(續)

 

單元測試系列之九:Sonar 常用代碼規則整理(一)

 

單元測試系列之十:Sonar 常用代碼規則整理(二)

 

單元測試系列之十一:Jmockit之mock特性詳解

 


免責聲明!

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



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