亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java程序員容易犯的10大低級錯誤

發布時間:2020-09-25 03:05:18 來源:腳本之家 閱讀:192 作者:交大全棧智能工程師 欄目:編程語言

本文根據java開發人員在編碼過程中容易忽視或經常出錯的地方進行了整理,總結了十個比較常見的低級錯誤點,方便大家學習。

1、不能用“==”比較兩個字符串內容相等。

2、 對list做foreach循環時,循環代碼中不能修改list的結構。

3、 日志和實際情況不一致;捕獲異常后沒有在日志中記錄異常棧。

4、 魔鬼數字。

5、 空指針異常。

6、 數組下標越界。

7、 將字符串轉換為數字時沒有捕獲NumberFormatException異常。

8、 對文件、IO、數據庫等資源進行操作后沒有及時、正確進行釋放。

9、 循環體編碼時不考慮性能,循環體中包含不需要的重復邏輯。

10、數據類沒有重載toString()方法。

1不能用“==”比較兩個字符串內容相等。

解讀

兩個字符串在比較內容是否相等的時候,如果使用“==”,當兩個字符串不是指向內存中同一地址,那么即使這兩個字符串內容一樣,但是用“==”比較出來的結果也是false。所以兩個字符串在比較內容是否相等的時候一定要使用“equals”方法。

示例

下面就是一個字符串比較的例子:

publicclass Test { 
publicstaticvoid main(String[] args) 
{ 
String a = new String("a"); 
String a2 = "a"; 
if(a == a2) 
{ 
System.out.println("a == a2return true."); 
} 
else 
{ 
System.out.println("a == a2 returnfalse."); 
} 
if(a.equals(a2)) 
{ 
 System.out.println("a.equals(a2)return true."); 
} 
else 
{ 
System.out.println("a.equals(a2)return false."); 
} 
} 
} 

最終輸出的結果為:

a == a2 return false. a.equals(a2) return true.

2 不能在foreach循環中修改list結構

解讀

在jdk1.5版以上的foreach循環寫法中,不能在循環代碼中對正在循環的list的結構進行修改,即對list做add、remove等操作,如果做了這些操作,必須立即退出循環,否則會拋出異常。

示例

publicclass Test { 
 publicstaticvoid main(String[] args) 
 { 
 List<Person> list = new ArrayList<Person>(); 
 Person p1 = new Person("張三", 23); 
 Person p2 = new Person("李四", 26); 
 Person p3 = new Person("王五", 34); 
 Person p4 = new Person("劉二", 15); 
 Person p5 = new Person("朱六", 40); 
 
 list.add(p1); 
 list.add(p2); 
 list.add(p3); 
 list.add(p4); 
 list.add(p5); 
 for(Person p : list) 
 { 
 if("王五".equals(p.getName())) 
 { 
 list.remove(p); // 不能在此時刪除對象。 
 } 
elseif("李四".equals(p.getName())) 
 { 
 list.remove(p); // 不能在此時刪除對象。 
 } 
 } 
 System.out.println(list.size()); 
 } 
} 
 
class Person 
{ 
 private String name; 
 privateintage; 
 
 public Person(String name, int age) 
 { 
 this.name = name; 
 this.age = age; 
 } 
 
 public String getName() 
 { 
 returnname; 
 } 
 
 publicvoid setName(String name) 
 { 
 this.name = name; 
 } 
 
 publicint getAge() 
 { 
 returnage; 
 } 
 
 publicvoid setAge(int age) 
 { 
 this.age = age; 
 } 
} 

解決上面代碼紅色部分的問題,可以通過循環取出對象,然后再循環結束后再進行刪除。

List<Person> list = new ArrayList<Person>(); 
 Person p1 = new Person(new String("張三"), 23); 
 Person p2 = new Person(new String("李四"), 26); 
 Person p3 = new Person(new String("王五"), 34); 
 Person p4 = new Person(new String("劉二"), 15); 
 Person p5 = new Person(new String("朱六"), 40); 
 
 list.add(p1); 
 list.add(p2); 
 list.add(p3); 
 list.add(p4); 
 list.add(p5); 
 
 Person wangwu = null; 
 Person lisi = null; 
 for(Person p : list) 
 { 
 if("王五".equals(p.getName())) 
 { 
 wangwu = p; 
 } 
 elseif("李四".equals(p.getName())) 
 { 
 lisi = p; 
 } 
 } 
 
 list.remove(wangwu); 
 list.remove(lisi); 

3 日志規范性

解讀

日志是定位問題時最重要的依據,業務流程中缺少必要的日志會給定位問題帶來很多麻煩,甚至可能造成問題完全無法定位。

異常產生后,必須在日志中以ERROR或以上級別記錄異常棧,否則會導致異常棧丟失,無法確認異常產生的位置。并不需要在每次捕獲異常時都記錄異常日志,這樣可能導致異常被多次重復記錄,影響問題的定位。但異常發生后其異常棧必須至少被記錄一次。

和注釋一樣,日志也不是越多越好。無用的冗余日志不但不能幫助定位問題,還會干擾問題的定位。而錯誤的日志更是會誤導問題,必須杜絕。

示例

下面的例子雖然打印了很多日志,但基本上都是無用的日志,難以幫助定位問題。甚至還有錯誤的日志會干擾問題的定位:

public voidsaveProduct1(ProductServiceStruct product) 
{ 
 log.debug("enter method: addProduct()"); 
 
 log.debug("check product status"); 
 if(product.getProduct().getProductStatus() != ProductFieldEnum.ProductStatus.RELEASE) 
 { 
 thrownew PMSException(PMSErrorCode.Product.ADD_ERROR); 
 } 
 
 log.debug("check tariff"); 
 BooleanResult result =checkTariff(product.getTariffs()); 
 if(!result.getResult()) 
 { 
 thrownewPMSException(PMSErrorCode.Product.ADD_ERROR); 
 } 
 
 log.debug("before add product"); 
 ProductService prodSrv = (ProductService)ServiceLocator.findService(ProductService.class); 
 try 
 { 
 prodSrv.addProduct(product); 
 } 
 catch(BMEException e) 
 { 
 // 未記錄異常棧,無法定位問題根源 
 } 
 
 log.debug("after add product"); 
 log.debug("exit method: updateProduct()"); // 錯誤的日志 
} 

而下面的例子日志打印的不多,但都是關鍵信息,可以很好的幫助定位問題:

public voidsaveProduct2(ProductServiceStruct product) 
{ 
 if(product.getProduct().getProductStatus() != ProductFieldEnum.ProductStatus.RELEASE) 
 { 
 log.error( 
 "productstatus " 
 +product.getProduct().getProductStatus() 
 + "error, expect " + ProductFieldEnum.ProductStatus.RELEASE); 
 thrownewPMSException(PMSErrorCode.Product.ADD_ERROR); 
 } 
 
 BooleanResult result =checkTariff(product.getTariffs()); 
 if(!result.getResult()) 
 { 
 log.error( 
 "checkproduct tariff error " 
 + result.getResultCode() 
 + ":" 
 + result.getResultDesc()); 
 thrownewPMSException(PMSErrorCode.Product.ADD_ERROR); 
 } 
 
 ProductService prodSrv = (ProductService)ServiceLocator.findService(ProductService.class); 
 try 
 { 
 prodSrv.addProduct(product); 
 } 
 catch(BMEException e) 
 { 
 log.error("add product error", e); 
 thrownewPMSException(PMSErrorCode.Product.ADD_ERROR,e); 
 } 
} 

4 魔鬼數字

解讀

在代碼中使用魔鬼數字(沒有具體含義的數字、字符串等)將會導致代碼難以理解,應該將數字定義為名稱有意義的常量。

將數字定義為常量的最終目的是為了使代碼更容易理解,所以并不是只要將數字定義為常量就不是魔鬼數字了。如果常量的名稱沒有意義,無法幫助理解代碼,同樣是一種魔鬼數字。

在個別特殊情況下,將數字定義為常量反而會導致代碼更難以理解,此時就不應該強求將數字定義為常量。

示例

public void addProduct(ProductServiceStruct product) 
{ 
 // 魔鬼數字,無法理解3具體代表產品的什么狀態 
 if(product.getProduct().getProductStatus() != 3) 
 { 
 thrownewPMSException(PMSErrorCode.Product.ADD_ERROR); 
 } 
 
 BooleanResult result =checkTariff(product.getTariffs()); 
 if(!result.getResult()) 
 { 
 thrownew PMSException(PMSErrorCode.Product.ADD_ERROR); 
 } 
} 
 
/** 
*產品未激活狀態 
*/ 
privatestaticfinalintUNACTIVATED = 0; 
/** 
*產品已激活狀態 
*/ 
privatestaticfinalintACTIVATED = 1; 
 
public voidaddProduct2(ProductServiceStruct product) 
{ 
 if(product.getProduct().getProductStatus() != ACTIVATED) 
 { 
 thrownewPMSException(PMSErrorCode.Product.ADD_ERROR); 
 } 
 
 BooleanResult result =checkTariff(product.getTariffs()); 
 if(!result.getResult()) 
 { 
 thrownewPMSException(PMSErrorCode.Product.ADD_ERROR); 
 } 
} 

5 空指針異常

解讀

空指針異常是編碼過程中最常見的異常,在使用一個對象的時候,如果對象可能為空,并且使用次對象可能會造成空指針異常,那么需要先判斷對象是否為空,再使用這個對象。

在進行常量和變量的相等判斷時,建議將常量定義為Java對象封裝類型(如將int類型的常量定義為Integer類型),這樣在比較時可以將常量放在左邊,調用equals方法進行比較,可以省去不必要的判空。

示例

public classNullPointer 
{ 
 staticfinal Integer RESULT_CODE_OK = 0; 
 staticfinal Result RESULT_OK = newResult(); 
 
 publicvoid printResult(Integer resultCode) 
 { 
 Result result = getResult(resultCode); 
 
 // result可能為null,造成空指針異常 
 if(result.isValid()) 
 { 
 print(result); 
 } 
 } 
 
 publicResult getResult(Integer resultCode) 
 { 
 // 即使resultCode為null,仍然可以正確執行,減少額外的判空語句 
 if(RESULT_CODE_OK.equals(resultCode)) 
 { 
 returnRESULT_OK; 
 } 
 returnnull; 
 } 
 
 publicvoid print(Result result) 
 { 
 ... 
 } 
}

6 下標越界

解讀

訪問數組、List等容器內的元素時,必須首先檢查下標是否越界,杜絕下標越界異常的發生。

示例

publicclass ArrayOver 
{ 
 publicvoid checkArray(String name) 
 { 
 // 獲取一個數組對象 
 String[] cIds = ContentService.queryByName(name); 
 if(null != cIds) 
 { 
 // 只是考慮到cids有可能為null的情況,但是cids完全有可能是個0長度的數組,因此cIds[0]有可能數組下標越界 
 String cid=cIds[0]; 
 cid.toCharArray(); 
 } 
 } 
} 

7 字符串轉數字

解讀

調用Java方法將字符串轉換為數字時,如果字符串的格式非法,會拋出運行時異常NumberFormatException。

示例

錯誤例子:

public Integer getInteger1(String number) 
{ 
 // 如果number格式非法,會拋出NumberFormatException 
 returnInteger.valueOf(number); 
} 

正確的處理方法如下:

public Integer getInteger2(String number) 
{ 
 try 
 { 
 returnInteger.valueOf(number); 
 } 
 catch(NumberFormatException e) 
 { 
 ... 
 //記錄日志異常信息 
 returnnull; 
 } 
}

注意:在捕獲異常后一定要記錄日志。

8 資源釋放

解讀

在使用文件、IO流、數據庫連接等不會自動釋放的資源時,應該在使用完畢后馬上將其關閉。關閉資源的代碼應該在try...catch...finally的finally內執行,否則可能造成資源無法釋放。

示例

錯誤案例如下:

public voidwriteProduct1(ProductServiceStruct product) 
{ 
 try 
 { 
 FileWriter fileWriter = new FileWriter(""); 
 fileWriter.append(product.toString()); 
 // 如果append()拋出異常,close()方法就不會執行,造成IO流長時間無法釋放 
 fileWriter.close(); 
 } 
 catch(IOException e) 
 { 
 ... 
 } 
} 

關閉IO流的正確方法如下:

public voidwriteProduct2(ProductServiceStruct product) 
{ 
 FileWriter fileWriter = null; 
 try 
 { 
 fileWriter = new FileWriter(""); 
 fileWriter.append(product.toString()); 
 } 
 catch(IOException e) 
 { 
 ... 
 //記錄日志 
 } 
 finally 
 { 
 // 不管前面是否發生異常,finally中的代碼一定會執行 
 if(fileWriter != null) 
 { 
 try 
 { 
 fileWriter.close(); 
 } 
 catch(IOException e) 
 { 
 ... 
 //記錄日志 
 } 
 } 
 } 
} 

注意:在捕獲異常后一定要記錄日志。

9 循環體性能

解讀

循環體是軟件中最容易造成性能問題的地方,所以在進行循環體編碼時務必考慮性能問題。

在循環體內重復使用且不會變化的資源(如變量、文件對象、數據庫連接等),應該在循環體開始前構造并初始化,避免在循環體內重復和構造初始化造成CPU資源的浪費。

除非業務場景需要,避免在循環體內構造try...catch塊,因為每次進入、退出try...catch塊都會消耗一定的CPU資源,將try...catch塊放在循環體之外可以節省大量的執行時間。

示例

public voidaddProducts(List<ProductServiceStruct> prodList) 
{ 
 for(ProductServiceStruct product : prodList) 
 { 
 // prodSrv在每次循環時都會重新獲取,造成不必要的資源消耗 
 ProductService prodSrv =(ProductService) ServiceLocator.findService(ProductService.class); 
 
 // 避免在循環體內try...catch,放在循環體之外可以節省執行時間 
 try 
 { 
 prodSrv.addProduct(product); 
 } 
 catch(BMEException e) 
 { 
 ... 
 //記錄日志 
 } 
 } 
} 

在循環體中遇到字符串相加,一定要使用StringBuffer這個類。

10 數據類重載toString()方法

解讀

數據類如果沒有重載toString()方法,在記錄日志的時候會無法記錄數據對象的屬性值,給定位問題帶來困難。

示例

public classMdspProductExt 
{ 
 privateString key; 
 privateString value; 
 publicString getKey() 
 { 
 returnkey; 
 } 
 publicvoid setKey(String key) 
 { 
 this.key = key; 
 } 
 publicString getValue() 
 { 
 returnvalue; 
 } 
 publicvoid setValue(String value) 
 { 
 this.value = value; 
 } 
} 
class BusinessProcess 
{ 
 privateDebugLog log = LogFactory.getDebugLog(BusinessProcess.class); 
 publicvoid doBusiness(MdspProductExtprodExt) 
 { 
 try 
 { 
 ... 
 } 
 catch(PMSException e) 
 { 
 // MdspProductExt未重載toString()方法,日志中無法記錄對象內屬性的值,只能記錄對象地址 
 log.error("error while process prodExt " +prodExt); 
 } 
 } 
} 

總結

以上所述是小編給大家介紹的Java程序員容易犯的10大低級錯誤,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

渝中区| 乌鲁木齐县| 额尔古纳市| 乳山市| 习水县| 马鞍山市| 社会| 平顶山市| 秦皇岛市| 永州市| 东丽区| 宁阳县| 简阳市| 永胜县| 墨江| 邢台市| 绥化市| 武夷山市| 高州市| 新野县| 苍梧县| 资中县| 汝南县| 阿巴嘎旗| 鄱阳县| 沈阳市| 卢龙县| 永胜县| 慈利县| 托克托县| 布尔津县| 陆丰市| 辽宁省| 凭祥市| 涿鹿县| 百色市| 前郭尔| 华容县| 临夏市| 桦南县| 微山县|