字符串和封裝類型應使用 equals()進行比較
例如java.lang.Integer使用引用等於==或!=,因為它不是比較實際值,而是比較內存中的位置。
String firstName = getFirstName(); // String overrides equals
String lastName = getLastName();
if (firstName == lastName) { ... }; // 即使字符串具有相同的值,也為false
方法參數,捕獲的異常和foreach變量的初始值不應忽略
public void doTheThing(String str, int i, List<String> strings) {
// str = Integer.toString(i); // 不符合規定
String str1 = str //在使用之前需要保存初始值
for (String s : strings) {
s = "hello world"; // Noncompliant
}
}
"InterruptedException" should not be ignored
在代碼中不應該忽略中斷異常,只在日志中打印異常日志,就像“忽略”一樣。拋出中斷異常會清除線程的中斷狀態,因此如果異常處理不當,那么線程被中斷的信息將會丟失。相反,中斷應該被重新拋出——立即或者在清理方法的狀態之后——或者應該通過調用Thread.interrupt()來重新中斷線程,即使這是單線程的應用程序。任何其他的操作過程都有延遲線程關閉的風險,並且丟失了線程被中斷的信息——線程很可能沒有完成它的任務。
類似地,也應該傳播ThreadDeath異常。根據它的JavaDoc:
如果ThreadDeath異常被一個方法捕獲,那么它被重新拋出是很重要的,這樣線程就會結束。
不符合要求的代碼如下:
public void run () {
try {
while (true) {
// do stuff
}
}catch (InterruptedException e) { // Noncompliant; logging is not enough
LOGGER.log(Level.WARN, "Interrupted!", e); // catch塊中只是打印了異常日志,相當於忽略了這個異常。
}
}
解決方案
//Compliant Solution
public void run () {
try {
while (true) {
// do stuff
}
}catch (InterruptedException e) {
LOGGER.log(Level.WARN, "Interrupted!", e);
// 恢復中斷狀態
Thread.currentThread().interrupt();
}
}
枚舉字段不應有public修飾的setter方法
enum通常被視為常量,但是enum帶有public字段或public的setter方法的不僅是非常量的,而且還容易受到惡意代碼的攻擊。理想情況下,枚舉字段應該用private修飾或者在構造器中賦值,但如果不可能,則應盡可能降低其可見性
反例
public enum Continent {
NORTH_AMERICA (23, 24709000),
// ...
EUROPE (50, 39310000);
public int countryCount; // 不合理
private int landMass;
Continent(int countryCount, int landMass) {
// ...
}
public void setLandMass(int landMass) { // 不合理
this.landMass = landMass;
}
規范寫法
public enum Continent {
NORTH_AMERICA (23, 24709000),
// ...
EUROPE (50, 39310000);
private int countryCount;
private int landMass;
public Continent(int countryCount, int landMass) {
// ...
}
void setCountryCount(int countryCount){
this.countryCount = countryCount;
}
public getCountryCount(){
return countryCount;
}
