国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
使用 IBM 靜態(tài)工具優(yōu)化 Java 代碼,第 2 部分: 分析錯(cuò)誤報(bào)告

 

概述

BEAM 報(bào)告的結(jié)果文件是通過 build.xml 中 --beam::complaint_file 所定義的,在這里,本文假設(shè)其為 BEAM-messages。BEAM-messages 記錄著報(bào)出的所有代碼缺陷,這些缺陷分為 ERROR,MISTAKEWARNING 三大類,嚴(yán)重程度依次遞減。每一個(gè)具體的 ERROR,MISTAKEWARNING 都代表著一個(gè)錯(cuò)誤模式,本文接下來就通過實(shí)例分析理解其中的某些重要錯(cuò)誤模式,告訴讀者在寫 Java 代碼時(shí)如何避免這些錯(cuò)誤模式的發(fā)生,從而寫出高質(zhì)量的代碼。

由于篇幅原因,本文只主要重點(diǎn)介紹四個(gè)常見的錯(cuò)誤模式,并在最后簡單介紹一下在編程時(shí)還應(yīng)該注意的一些其它技巧,文章結(jié)構(gòu)如下:

  • 操作空對象
  • 數(shù)組訪問越界
  • 除 0 錯(cuò)誤
  • 內(nèi)存泄漏
  • 其它技巧

操作空對象

這是報(bào)出的 ERROR2 錯(cuò)誤模式。據(jù)個(gè)人項(xiàng)目經(jīng)驗(yàn),這種錯(cuò)誤模式出現(xiàn)最為頻繁,但是編程人員卻往往很難發(fā)現(xiàn),因?yàn)檫@種編譯器發(fā)現(xiàn)不了的錯(cuò)誤可能在代碼運(yùn)行很長時(shí)間時(shí)都不會發(fā)生,可是一旦出現(xiàn),程序就會終止運(yùn)行,并拋出 runtime 異常 java.lang.NullPointerException。通常有以下這些情況會導(dǎo)致操作空對象錯(cuò)誤模式的發(fā)生。

  • 調(diào)用空對象的方法
  • 訪問或修改空對象的域
  • 訪問或修改空數(shù)組對象的數(shù)組元素
  • 同步空對象
  • 傳入空對象參數(shù)

下面讓我們用簡單易懂的例子一一介紹它們。

調(diào)用空對象的方法


清單 1. 調(diào)用空 String 對象的 charAt() 方法

  1. String str = null
  2.  int a = 0;    
  3.  if( a > 0 ) { 
  4.      str = new String[]{ "developer " , "Works"}; 
  5.  } 
  6.  char ch = str.charAt(0); 

這是最典型的調(diào)用空對象方法的例子,調(diào)用一個(gè)未初始化的 String 對象的 chatAt() 方法。


清單 2. 調(diào)用未初始化數(shù)組成員的方法

 

  1. Integer[] array = null
  2.  try
  3.      array = new Integer[] { new Integer(2/0), new Integer(3), new Integer(4) }; 
  4.  } catch ( Exception e ) { 
  5.       //Do nothing here 
  6.  } 
  7.  int i = array[0].intValue(); 

數(shù)組 array 的三個(gè) Integer 成員因?yàn)槌龜?shù)為 0 的異常并沒有被初始化(這里只是用典型的除數(shù)為 0 的異常舉例,其實(shí)實(shí)際工程中,初始化時(shí)發(fā)生的異常有時(shí)很難被發(fā)現(xiàn),沒有如此明顯),但是接下來仍然調(diào)用其第 0 個(gè)成員的 intValue() 方法。

總結(jié):調(diào)用空對象方法的錯(cuò)誤非常常見,導(dǎo)致其出現(xiàn)的原因通常有兩點(diǎn):

  1. 在某個(gè)方法開始處定義了空對象,程序員準(zhǔn)備在其后的代碼中對其進(jìn)行初始化,初始化完畢后再調(diào)用該對象的方法。但是有時(shí)由于初始化代碼中的某個(gè)不常見的 if 之類的條件不成立或者 for/while 循環(huán)的條件不成立,導(dǎo)致接下來的賦值動作并沒有進(jìn)行,其結(jié)果就是之前定義的空對象并沒有被初始化,然后又調(diào)用該對象的方法,從而造成了 java.lang.NullPointerException,如清單 1 所示。
  2. 初始化對象時(shí)出現(xiàn)了異常,但是沒有對異常進(jìn)行特殊處理,程序接下來繼續(xù)運(yùn)行,導(dǎo)致最終調(diào)用了該空對象的方法,如清單 2 所示。

這種代碼缺陷在大型代碼工程中往往很難被發(fā)現(xiàn),因?yàn)榫幾g器不會報(bào)錯(cuò),而且代碼在實(shí)際運(yùn)行中,可能 99% 的時(shí)候 if 條件都是滿足的,初始化也是成功的,所以程序員很難在測試中發(fā)現(xiàn)該問題,但是這種代碼一旦交付到用戶手中,發(fā)現(xiàn)一次就是災(zāi)難性的。

建議的解決方法:一定要明確知道即將引用的對象是否是空對象。如果在某個(gè)方法中需要調(diào)用某個(gè)對象,而此對象又不是在本方法中定義(如:通過參數(shù)傳遞),這時(shí)就很難在此方法中明確知道此對象是否為空,那么一定要在調(diào)用此對象方法之前先判斷其是否為空,如果不為空,然后再調(diào)用其方法,如:if( obj != null ) { obj.method() … }

訪問或修改空對象的域

定義了某個(gè)類的對象,在沒有對其初始化之前就試圖訪問或修改其中的域,同樣會導(dǎo)致 java.lang.NullPointerException 異常。這種情況也非常常見,舉一個(gè)比較典型的數(shù)組對象的例子,如清單 3 所示:


清單 3. 訪問未初始化數(shù)組的 length

 

  1. String[] str = null
  2.  int a = 0;    
  3.  while( a > 0 ) { 
  4.  str = new String[]{"developer""Works"}; 
  5.  } 
  6.  System.out.println( str.length ); 

數(shù)組 str 由于某些條件并沒有被初始化,但是卻訪問其 public finallength 想得到其長度。

總結(jié):訪問或修改某個(gè)空對象的域的起因與調(diào)用空對象的方法類似,通常是由于某些特殊情況導(dǎo)致原本應(yīng)該初始化的數(shù)組對象沒有被初始化,從而接下來訪問或修改其域時(shí)產(chǎn)生 java.lang.NullPointerException異常。

建議的解決方法:與調(diào)用空對象的方法類似,盡量在訪問或修改某些不能夠明確判斷是否為空對象的域之前,對其進(jìn)行空對象判斷,從而避免對空對象的操作。

訪問或修改空數(shù)組對象的數(shù)組元素

當(dāng)某個(gè)數(shù)組為空時(shí),試圖訪問或修改其數(shù)組元素時(shí)都會拋出 java.lang.NullPointerException 異常。


清單 4. 訪問或修改空數(shù)組對象的數(shù)組元素
            1   String[] str = null;            2   System.out.println( str[0]);            3   str[0] = "developerWorks" ;            

第 2 行和第 3 行都會導(dǎo)致 ERROR2 錯(cuò)誤,其中第 2 行試圖訪問空數(shù)組對象 str 的第 0 個(gè)元素,第 3 行試圖給空數(shù)組對象 str 的第 0 個(gè)元素賦值。

總結(jié):訪問或修改某個(gè)空數(shù)組對象的數(shù)組元素的起因與調(diào)用空對象的方法類似,通常是由于某些特殊情況導(dǎo)致原本應(yīng)該初始化的數(shù)組對象沒有被初始化,從而接下來訪問或修改其數(shù)組元素時(shí)產(chǎn)生 java.lang.NullPointerException 異常。

建議的解決方法:與調(diào)用空對象的方法類似,盡量在訪問或修改某些不能夠明確判斷是否為空空數(shù)組對象的數(shù)組元素之前,對其進(jìn)行空對象判斷,從而避免對空數(shù)組對象的操作。

同步空對象


清單 5. 同步空對象

 

  1. String s = null
  2.  int a = 0;    
  3.  switch( a ) { 
  4.     case 1: s = new String("developer"); 
  5.     case 2: s = new String("Works"); 
  6.     default
  7.  ; 
  8.  } 
  9.  synchronized( s ){ 
  10.     ……
  11.  } 

對空對象 s 進(jìn)行同步。

總結(jié):同步空對象的起因與調(diào)用空對象的方法類似,通常是由于某些特殊情況導(dǎo)致原本應(yīng)該初始化的對象沒有被初始化,從而接下來導(dǎo)致同步空對象,并產(chǎn)生 java.lang.NullPointerException 異常。

建議的解決方法:與調(diào)用空對象的方法類似,盡量在同步某些不能夠明確判斷是否為空的對象之前,對其進(jìn)行空對象判斷,從而避免對空對象的操作。

傳入空對象參數(shù)


清單 6 傳入空對象參數(shù)

 

  1. static int getLength( String string ) { 
  2.  return string.length(); 
  3.  } 
  4.  public static void main(String[] args) { 
  5.  String string = null
  6.  int len = getLength( string ); 
  7.  } 

將空 String 對象 string 傳入 getLength 方法,從而導(dǎo)致在 getLength 方法內(nèi)產(chǎn)生 java.lang.NullPointerException 異常。

總結(jié):導(dǎo)致傳入空對象參數(shù)的原因通常是在傳參前忘記對參數(shù)對象是否為空進(jìn)行檢查,或者調(diào)用了錯(cuò)誤的方法,或者假定接下來傳參的函數(shù)允許空對象參數(shù)。

建議的解決方法:如果函數(shù)的參數(shù)為對象,并且在函數(shù)體中需要操作該參數(shù)(如:訪問參數(shù)對象的方法或域,試圖修改參數(shù)對象的域等),一定要在函數(shù)開始處對參數(shù)是否為空對象進(jìn)行判斷,如果為空則不再執(zhí)行函數(shù)體,并最好作特殊處理,達(dá)到避免操作空對象的目的。


數(shù)組訪問越界

這是報(bào)出的 ERROR7 錯(cuò)誤模式。什么是數(shù)組訪問越界呢?如果一個(gè)數(shù)組(在 Java 中,Vector,ArrayListList也算是數(shù)組類型)定義為有 n 個(gè)元素,那么對這 n 個(gè)元素(0~n-1)的訪問都是合法的,如果對這 n個(gè)元素之外的訪問,就是非法的,稱為“越界”。這種錯(cuò)誤同樣不會造成編譯錯(cuò)誤,會危險(xiǎn)地“埋伏”在你的程序中。在 C/C++中遇到數(shù)組訪問越界,可導(dǎo)致程序崩潰,甚至宕機(jī);在 Java 中,會拋出 runtime 異常 java.lang.ArrayIndexOutOfBoundsExceptionjava.lang.IndexOutOfBoundsException,并終止程序運(yùn)行。請看程序員容易犯的幾個(gè)典型數(shù)組訪問越界的例子:


清單 7. 越界訪問 String 數(shù)組元素 1

            int index = 2;            String[] names = new String[] { "developer", "Works" };            System.out.println( names[index] );            

index 為 2,而數(shù)組只有兩個(gè)元素,最后一個(gè)元素的下標(biāo)索引是 1,所以導(dǎo)致數(shù)組訪問越界。注意,如果 index 為負(fù)數(shù),仍然是數(shù)組訪問越界。


清單 8. 越界訪問 Vector

            Vector<String> vec = new Vector<String>();            for ( int i = 0; i <= vec.size(); i ++ ) {            System.out.println( vec.get(i) );            }            

VectorArrayList 的起始索引是 0,所以用其數(shù)組大小作為索引會導(dǎo)致數(shù)組訪問越界,其數(shù)組最后一個(gè)元素的索引應(yīng)該是“數(shù)組大小 -1 ”。


清單 9. 越界訪問 String 數(shù)組元素 2

  1. int a = 0; 
  2.  String[] names = null
  3.  StringBuffer buf = new StringBuffer(); 
  4.     
  5.  if ( a > 0 ) { 
  6.      names = new String[] { "developer""Works" }; 
  7.  } else { 
  8.      names = new String[] { "developerWorks" }; 
  9.  } 
  10.         
  11.  buf.append( names[0] ).append( names[1] ); 

程序員調(diào)用 append 時(shí)以為數(shù)組 names 中有兩個(gè)元素,其實(shí)只有一個(gè)。


清單 10. 越界訪問 ArrayList

 

  1. ArrayList<String> arrList = new ArrayList<String>(); 
  2.  int len = 5; 
  3.     
  4.  forint i = 0; i < len; i++ ) { 
  5.  arrList.add( String.valueOf(i) ); 
  6.  } 
  7.     
  8.  arrList.remove( len - 1 ); 
  9.  System.out.println(arrList.get( len - 1 )); 

ArrayList 中最后一個(gè)元素已經(jīng)被 remove 了,所以該位置已經(jīng)沒有任何東西,訪問它將導(dǎo)致 java.lang.ArrayIndexOutOfBoundsException。

總結(jié):導(dǎo)致數(shù)組訪問越界主要有以下幾個(gè)原因:

  1. 使用某個(gè)變量作為數(shù)組索引時(shí),沒有之前對該變量值進(jìn)行檢查,變量的取值可能會超出合法的數(shù)組索引范圍,從而導(dǎo)致數(shù)組訪問越界,如清單 7 。
  2. 使用與數(shù)組元素個(gè)數(shù)相同的值作為數(shù)組索引,因?yàn)閿?shù)組的最后一個(gè)元素的索引是“數(shù)組大小 -1 ”,所以導(dǎo)致數(shù)組訪問越界,如清單 8 。
  3. 數(shù)組初始化代碼中某個(gè)不起眼的 if 之類的條件不成立或者 for/while循環(huán)的條件不成立,導(dǎo)致接下來的賦值動作并沒有進(jìn)行,從而接下來訪問了未初始化完全的數(shù)組,導(dǎo)致數(shù)組訪問越界,如清單 9 。
  4. 程序員編碼時(shí)忘記 Vector,ArrayListList 中某些位置的元素已經(jīng)被 remove 了,后來仍然對該位置元素進(jìn)行訪問,可能會導(dǎo)致數(shù)組訪問越界,如清單 10 。

建議的解決方法:在判斷數(shù)組是否有效不為空的同時(shí),也要對訪問的數(shù)組元素的索引是否超出了上下限進(jìn)行檢查,如果索引是個(gè)變量,一定要確保變量取值在數(shù)組范圍之類(反例是清單 7);如果索引不是個(gè)變量,在確保索引正確的同時(shí)還要確保之前定義的數(shù)組足夠大(反例是清單 9)。最好是使用 try/catch 訪問數(shù)組,并對數(shù)組訪問越界異常進(jìn)行捕獲,進(jìn)行特殊處理,如清單 11 。


清單 11 利用 try/catch 安全訪問數(shù)組

 

  1. try { 
  2.  // 訪問數(shù)組
  3.  } 
  4.  catch( IndexOutOfBoundsException e ) { 
  5.  // 捕獲數(shù)組訪問越界的異常并做特殊處理
  6.  } 

除 0 錯(cuò)誤

這是報(bào)出的 ERROR22 錯(cuò)誤模式。在 Java 中,如果除數(shù)為 0,會導(dǎo)致 runtime 異常 java.lang.ArithmeticException 并終止程序運(yùn)行,如清單 12 所示。


清單 12 除數(shù)為 0
            int num = 0;            …            int a = 5 / num;            

總結(jié):導(dǎo)致除 0 錯(cuò)誤的主要原因是使用變量作為除數(shù),并且程序員在寫除法語句時(shí),以為變量值到此已經(jīng)被改變(不是 0),但是實(shí)際上可能某條不被注意的語句路徑導(dǎo)致除數(shù)為 0,從而造成了錯(cuò)誤。

建議的解決方法:做除法前,一定不能將除數(shù)直接寫為 0 ;如果除數(shù)為變量,而且該變量值在進(jìn)行除法前經(jīng)過了很多運(yùn)算,導(dǎo)致不能確定在被除前是否為 0,則在除法前,先對除數(shù)變量進(jìn)行是否為 0 的判斷,并對除數(shù)為 0 的情況做特殊處理。

內(nèi)存泄漏

這是報(bào)出的ERROR23錯(cuò)誤模式。內(nèi)存泄漏的后果非常嚴(yán)重,即使每次運(yùn)行只有少量內(nèi)存泄漏,但是長期運(yùn)行之后,系統(tǒng)仍然會面臨徹底崩潰的危險(xiǎn)。

在 C/C++ 中,內(nèi)存泄漏(MemoryLeak)一直是程序員特別頭疼的問題,因?yàn)樗鲥e(cuò)時(shí)的表現(xiàn)特征經(jīng)常很不穩(wěn)定(比如:錯(cuò)誤表象處不唯一,出錯(cuò)頻率不定等),而且出現(xiàn)問題的表象處經(jīng)常與內(nèi)存泄漏錯(cuò)誤代碼相隔甚遠(yuǎn),所以很難被定位查出。在 Java 中,垃圾回收器 (Garbage Collection,GC)的出現(xiàn)幫助程序員實(shí)現(xiàn)了自動管理內(nèi)存的回收,所以很多程序員認(rèn)為 Java不存在內(nèi)存泄漏問題,其實(shí)不然,垃圾回收器并不能解決所有的內(nèi)存泄漏問題,所以 Java 也存在內(nèi)存泄漏,只是表現(xiàn)與 C/C++ 不同。

為什么 Java 會出現(xiàn)內(nèi)存泄漏呢?因?yàn)槔厥掌髦换厥漳切┎辉俦灰玫膶ο?。但是有些對象的的確確是被引用的(可達(dá)的),但是卻無用的(程序以后不再使用這些對象),這時(shí)垃圾回收器不會回收這些對象,從而導(dǎo)致了內(nèi)存泄漏,拋出異常 java.lang.OutOfMemoryError。以下是導(dǎo)致內(nèi)存泄漏的常見的例子(其中某些例子 BEAM 很難查出,這里列出只是為了給讀者提供一個(gè)反例進(jìn)行學(xué)習(xí))。


清單 13. 內(nèi)存泄漏的 Hashtable

  1. public class HashtableLeakDemo 
  2.  { 
  3.  static Hashtable<Integer, String> names = new Hashtable<Integer, String>(); 
  4.  void leakingHash( int num ) { 
  5.      forint i = 0; i < num; i++ ) { 
  6.      names.put( new Integer(i) , "developerWorks"); 
  7.      } 
  8.      // 接下來是繼續(xù)對 names 哈希表進(jìn)行的操作,但是忘了移除其中的表項(xiàng)
  9.  } 
  10.  } 

leakingHash 會往 Hashtable 中不停地加入元素,但是卻沒有相應(yīng)的移除動作(remove),而且 staticHashtable 永遠(yuǎn)都會貯存在內(nèi)存中,這樣必將導(dǎo)致 Hashtable 越來越大,最終內(nèi)存泄漏。


清單 14. 內(nèi)存泄漏的 Vector

 

  1. public class VectorLeakDemo 
  2.  { 
  3.  static Vector<String> v = new Vector<String>(); 
  4.  void leakingVector( int num ) { 
  5.      forint i = 0; i < num; i++ ) { 
  6.      v.add( String.valueOf(i) ); 
  7.      } 
  8.      // 雖然進(jìn)行了 remove,但是卻沒有移除干凈
  9.      forint i = num - 1; i > 0; i--  ) { 
  10.      v.remove( i ); 
  11.      } 
  12.  } 
  13.  } 

每次調(diào)用 leakingVector 都會少 remove 一個(gè) String 元素,如果 Vector 中的元素不是 String,而是數(shù)據(jù)庫中一些非常大的記錄(record),那么不停調(diào)用 leakingVector 將很快導(dǎo)致內(nèi)存耗光。


清單 15. 內(nèi)存泄漏的 Buffer

 

  1. public class BufferLeakDemo 
  2.  { 
  3.      private byte[] readBuffer; 
  4.     
  5.      public void readFile( String fileName ) { 
  6.           File f = new File( fileName ); 
  7.         
  8.           int len = (int)f.length(); 
  9.           //readBuffer 的長度只增不減
  10.           if ( readBuffer == null || readBuffer.length < len ) { 
  11.                readBuffer = new byte[len]; 
  12.           } 
  13.         
  14.           readFileIntoBuf( f, readBuffer ); 
  15.      } 
  16.     
  17.      public void readFileIntoBuf( File f, byte[] buffer ) { 
  18.           // 將文件內(nèi)容讀取到 buffer 中
  19.      } 
  20.  } 

BufferLeakDemo 對象的生命周期中,一直會有一個(gè) readBuffer 存在,其長度等于讀到的所有文件中最長文件的長度,而且更糟糕的是,該 readBuffer 只會增大,不會減小,所以如果不停的讀大文件,就會很快導(dǎo)致內(nèi)存泄漏。


清單 16. 內(nèi)存泄漏的 Stream 流 1

 

  1. public void writeFile( String fileName ) { 
  2.  OutputStream writer = null
  3.  writer = new FileOutputStream(fileName); 
  4.         // 接下來對 writer 進(jìn)行操作,但是結(jié)束后忘記關(guān)閉 close 
  5.  } 

文件輸出流 FileOutputStream 使用完了沒有關(guān)閉,導(dǎo)致 Stream 流相關(guān)的資源沒有被釋放,內(nèi)存泄漏。


清單 17. 內(nèi)存泄漏的 Stream 流 2

 

  1. public void writeFile( String srcFileName, String dstFileName )  { 
  2.  try { 
  3.      InputStream reader = new FileInputStream( srcFileName ); 
  4.      OutputStream writer = new FileOutputStream( dstFileName ); 
  5.             
  6.      byte[] buffer = new byte[1024]; 
  7.        
  8.         // 將源文件內(nèi)容讀入到 buffer 中   
  9.      reader.read(buffer); 
  10.      // 將 buffer 中的數(shù)據(jù)寫入到目的文件中
  11.      writer.write(buffer); 
  12.             
  13.      reader.close(); 
  14.      writer.close(); 
  15.  } catch ( Exception e ) { 
  16.        // 對異常情況進(jìn)行處理 
  17.  } 
  18.  } 

如果 reader 讀取文件時(shí) InputStream 發(fā)生異常,那么 writer 將不會被關(guān)閉,從而導(dǎo)致內(nèi)存泄漏。

總結(jié):

  1. 一些 Collection 類,如 Hashtable,HashSet,HashMap,VectorArrayList 等,程序員使用時(shí)一般容易忘記 remove 不再需要的項(xiàng)(如清單 13),或者雖然 remove,但是 remove 的不干凈(如清單 14),這些都可能會導(dǎo)致無用的對象殘留在系統(tǒng)中,這樣的程序長時(shí)間運(yùn)行,可能會導(dǎo)致內(nèi)存泄漏。特別是當(dāng)這些 Collection 類的對象被聲明為 static 時(shí)或存活于整個(gè)程序生命周期時(shí),就更容易導(dǎo)致內(nèi)存泄漏。
  2. 有些 buffer 在其生命周期中有時(shí)可能會很大,大到有可能導(dǎo)致內(nèi)存泄漏(如清單 15)。
  3. 使用 Stream 流時(shí)(如 FileOutputStream,PrintStream 等),創(chuàng)建并使用完畢后忘記關(guān)閉 close(如清單 16),或者因?yàn)楫惓G闆r使得關(guān)閉 Stream 流的 close 的語句沒有被執(zhí)行(如清單 17),這些都會導(dǎo)致 Stream 流相關(guān)的資源沒有被釋放,從而產(chǎn)生內(nèi)存泄漏。

建議的解決方法:

  1. 程序員編碼時(shí)注意手動釋放一些已經(jīng)明確知道不再使用的對象。最簡單的方法就是將其置為 null,告訴垃圾回收器你已經(jīng)不再引用他們,從而垃圾回收器可以替你回收這些對象所占用的內(nèi)存空間。
  2. 使用 Collection 類對象時(shí)(如 Hashtable,HashSet,HashMap,VectorArrayList 等),如果可以,盡量定義其為局部變量,減少外界對其的引用,增大垃圾回收器回收他們的可能性。
  3. 使用 Collection 類對象時(shí)(如 Hashtable,HashSetHashMap,VectorArrayList 等),注意手動 remove 其中不再使用的元素,減少垃圾對象的殘留。
  4. 使用事件監(jiān)聽器時(shí)(event listener),記住將不再需要監(jiān)聽的對象從監(jiān)聽列表中解除(remove)。
  5. 使用 Stream 流時(shí),一定要注意創(chuàng)建成功的所有 Stream 流一定要在使用完畢后 close 關(guān)閉,否則資源無法被釋放。
  6. try / catch 語句中,添加 finally 聲明,對 try 中某些可能因?yàn)楫惓6鴽]釋放的資源進(jìn)行釋放。
  7. 在 class 中添加 finalize() 方法,手動對某些資源進(jìn)行垃圾回收。
  8. 可以使用一些可以檢測內(nèi)存泄漏的工具,如 Optimizeit Profiler,JProbe Profiler,JinSight, Rational 公司的 Purify 等,來幫助找出代碼中內(nèi)存泄漏的錯(cuò)誤。

其它技巧

  • 使用 Iterator 時(shí),一定要先調(diào)用 hasNext() 后,再調(diào)用 next(),而且不要在一個(gè) Iterator 的 hasNext() 成功后,去調(diào)用另外一個(gè) Iterator 的 next(),如清單 18 。

    清單 18. 使用 Iterator 出錯(cuò)
                    Iterator firstnames = ( new Vector() ).iterator();                Iterator lastnames =  ( new Vector() ).iterator();                while ( firstnames.hasNext() ) {                //firstnames 中存在下一個(gè)元素,但 lastnames 可能已經(jīng)沒有元素了                String name = firstnames.next() + "." + lastnames.next();                }                

  • 注意 switch 語句中是否缺少 break 。有的時(shí)候程序員有意讓多個(gè) case 語句在一次執(zhí)行,但是有的時(shí)候卻是忘寫 break,導(dǎo)致發(fā)生了意想不到的結(jié)果,如清單 19 。

    清單 19. switch 語句中缺少 break
                    switch ( A )                {                // 程序員原本的意思是 A 為 0 時(shí),B 為 0,A 為 1 時(shí),B 為 1,其實(shí) B 永遠(yuǎn)都不可能為 0                case 0: B = 0;                case 1: B = 1; break;                }                

  • 注意避免恒正確或恒錯(cuò)誤的條件,如清單 20 。

    清單 20. 常見的恒正確或恒錯(cuò)誤的條件
                    例 1:                if ( S.length() >= 0 ) // S 是 String 對象,它的長度永遠(yuǎn)大于等于 0,條件恒正確                例 2:                // 程序員本來的意圖是想介于 MIN 和 MAX 之間的值才成立,卻誤將” && ”寫成” || ”,導(dǎo)致條件恒成立                if ( x >= MIN || x <= MAX )                例 3:                final boolean singleConnection = true;                // final 型的 singleConnection 永遠(yuǎn)為 true,所以該條件恒成立,而且 connect() 永遠(yuǎn)不會被執(zhí)行                if ( singleConnection || connect() )                

  • 注意在 if 語句中是否少了 else 分支,如清單 21。

    清單 21. if 語句中少了 else 分支
                    if ( S == “ d ” ) { … }                else if ( S == “ e ” ) { … }                else if ( S == “ v ” ) { … }                else if ( S == “ e ” ) { … }                // 少了 else 語句,漏掉的情況可能會產(chǎn)生異常,應(yīng)該加上 else 語句對剩下的條件進(jìn)行判斷和處理                

  • switch 語句最好對所有的 case 進(jìn)行判斷,并且不要忘記對 default 情況進(jìn)行處理。

 

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
java代碼效率優(yōu)化
Java容器學(xué)習(xí)筆記(一) 容器中基本概念及Collection接口相關(guān)知識
解決內(nèi)存泄漏問題
Java中的集合類綜述
第一部分 基礎(chǔ)語言之三數(shù)組和指針
C++ Primer 第三章字符串,向量和數(shù)組
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服