1. 程式人生 > >java異常及錯誤處理大綱

java異常及錯誤處理大綱

文章目錄

1.異常處理

異常(exception ) 又稱為例外、差錯、違例
對應著Java執行錯誤處理機制
基本寫法

try{ 
  語句組 
}catch(Exception ex){ 
 異常處理語句組;  
}
import java.io.*;
public class ExceptionForNum 
{
	public static void main(String[] args) 
	{
		try
{ BufferedReader in = new BufferedReader( new InputStreamReader( System.in ) ); System.out.print("Please input a number: "); String s = in.readLine(); int n = Integer.parseInt( s ); }catch(IOException ex){ ex.printStackTrace(); }catch(NumberFormatException ex){ ex.printStackTrace
(); } } }

傳統的 語言如何處理

在一些傳統的語言(如C語言中)
if語句來判斷是否出現了例外
全程變數ErrNo

但這有幾個缺點
正常處理與異常處理的程式碼同樣處理
可讀性(readability)差

每次呼叫一個方法時都進行錯誤檢查
​ 可維護性( maintainability )差

​ 錯誤由誰處理不請
​ 職責不清

Java中處理異常
丟擲(throw)異常
執行時系統在呼叫棧中查詢
​ 從生成異常的方法開始進行回溯,直到找到:
​ 捕獲(catch) 異常的程式碼

相關的語句
丟擲異常

throw 異常物件;

捕獲異常

 try
{ 語句組 }catch(異常類名 異常形式引數名){ 異常處理語句組; }catch(異常類名 異常形式引數名){ 異常處理語句組; }finally{ 異常處理語句組; }

其中,catch語句可以0至多個,可以沒有finally語句

異常的分類

Throwable (可丟擲)
Error: JVM的錯誤
Exception: 異常
一般所說的異常
是指Exception及其子類

Exception類

構造方法
public Exception();
public Exception(String message);
Exception(String message, Throwable cause) ;
​ 方法
​ getMessage()
​ getCause()
​ printStackTrace()

多異常的處理
子類異常要排在父類異常的前面

finally語句
無論是否有異常都要執行
即使其中有break,return等語句
在編譯時,finally部分程式碼生成了多遍

package ch5;

public class text1 {
    public static String output = "";

    public static void foo(int i) {
        try {
            if (i == 1) {
                throw new Exception();
            }
            output += "1";
        } catch(Exception e) {
            output += "2";
            return;
        } finally {
            output += "3";
        }
        output += "4";
    }

    public static void main(String args[]) {
        //foo(0);
        //System.out.print(output + " ");
        foo(1);
        System.out.println(output);
    }
}
//最後結果是23這說明,不管之前catch裡是什麼語句,都會執行finally語句

Exception分兩種
RuntimeException及其子類,可以不明確處理
否則,稱為受檢的異常(checked Exception)

受檢的異常,要求明確進行語法處理
要麼捕(catch)
要麼拋(throws):在方法的簽名後面用throws xxxx來宣告

在子類中,如果要覆蓋父類的一個方法,若父類中的方法聲明瞭 throws異常,則子類的方法也可以throws異常
可以丟擲子類異常(更具體的異常),但不能丟擲更一般的異常

package ch5;

import java.io.FileInputStream;
import java.io.IOException;
public class text1{
	public static void main(String[] args){
	
		try{
			System.out.println("====Before====");
		 	readFile();
			System.out.println("====After====");
		 }catch(IOException e){ System.out.println(e); }
	}

	public static void readFile()throws IOException {
		FileInputStream in=new FileInputStream("myfile.txt");
		int b;	
		b = in.read();
		while(b!= -1)   {
			System.out.print((char)b);
			b = in.read();
		}
		in.close();	
	}
}

try…with…resource

try(型別 變數名 = new 型別() ){
。。。
}
自動添加了finally{ 變數.close(); }
不論是否出現異常,都會執行

package ch5;

import java.io.*;
class TryWithResourcesTest {
    public static void main(String ... args)
		throws IOException
	{
		String path = "c:\\aaa.txt";
		System.out.println( ReadOneLine1( path ) );
		System.out.println( ReadOneLine2( path ) );
    }
	static String ReadOneLine1(String path){
		BufferedReader br=null;
        try {
            br=new BufferedReader(new FileReader(path));
            return br.readLine();
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            if(br!=null){
				try{ 
					br.close();
				}catch(IOException ex){
				}
			}
        }
		return null;
	}
	static String ReadOneLine2(String path)
		throws IOException
	{
		try(BufferedReader br= new BufferedReader(new FileReader(path))){
            return br.readLine();
        }
	}
}

2. 自定義異常

建立使用者自定義異常類
建立使用者自定義異常時
(1) 繼承自Exception類或某個子Exception類
(2) 定義屬性和方法,或過載父類的方法
重拋異常及異常連結
對於異常,不僅要進行捕獲處理,有時候還需要將此異常進一步傳遞給呼叫者,以 便讓呼叫者也能感受到這種異常。這時可以在catch語句塊或finally語句塊中採取 以下三種方式:
(1)將當前捕獲的異常再次丟擲:
throw e;

(2)重新生成一個異常,並丟擲,如:
throw new Exception(“some message”);
(3)重新生成並丟擲一個新異常,該異常中包含了當前異常的資訊,如:
throw new Exception(“some message”,e);
可用e.getCause() 來得到內部異常

public class ExceptionCause {
	public static void main(String [] args)	{
		try 
		{
			BankATM.GetBalanceInfo( 12345L);
		}catch(Exception e)	{
			System.out.println("something wrong�� " + e);
			System.out.println("cause��" + e.getCause());
		}
	}
}

class DataHouse {
	public static void FindData( long ID)
		throws DataHouseException
	{
		if( ID>0 && ID<1000)
			System.out.println( "id: " + ID );
		else
			throw new DataHouseException("cannot find the id");
	}
}
class BankATM{
	public static void GetBalanceInfo( long  ID)
		throws MyAppException
	{
		try 
		{
			DataHouse.FindData(ID);
		}catch (DataHouseException e) {
			throw new MyAppException("invalid id",e);
		}
	}
}
class DataHouseException extends Exception {
	public DataHouseException( String message ) {
		super(message);
	}
}
class MyAppException extends Exception {
	public MyAppException (String message){ 
		super (message); 
	}
	public MyAppException (String message, Exception cause) {
		super(message,cause);
	}   
}

3. 斷言及程式的測試

斷言(assertion)
assert的格式是:
assert 表示式; (邏輯表示式)
assert 表示式 : 資訊;
在除錯程式時
如果表示式不為true,則程式會產生異常,並輸出相關的錯誤資訊

class Assertion {
	public static void main(String[] args)	{
		assert hypotenuse(3,4)==5 : "演算法不正確";
	}
	static double hypotenuse( double x, double y ){
		return Math.sqrt( x*x + y*y + 1);
	}
}

Assert 的編譯及執行
編譯
只有在JDK1.4及以上的版本中才可以使用斷言。
具體地說,在早期的JDK版本(1.4)中編譯時,要通過-source選項來指明版本,如:
javac -deprecation -source 1.4 -classpath . Assertion.java
執行
在執行時,要使assert起作用,則在java命令中,使用選項(-ea,即-enableassertions)。如:
java -ea -classpath . Assertion

程式的測試及 JUnit
程式的修改是經常要進行的過程,必須保證程式在修改後其結果仍然 是正確的。
在編寫程式程式碼的同時,還編寫測試程式碼來判斷這些程式是否正確。
這個過程稱為“測試驅動”的開發過程。
從而保證了程式碼的質量,減少了後期的查錯與除錯的時間,所以實際 上它提高了程式的開發效率。

JUnit
在Java的測試過程,經常使用JUnit框架
參見http://www.junit.org。
現在大多數Java整合開發工具都提供了對JUnit的支援。
在Eclipse中
專案右鍵—New— Junit Test Case
專案右鍵—Run as — Junit Test
測試通過則為綠色,不通過顯示紅色
在NetBeans中
專案右鍵—新建— Junit測試
執行—測試,或者直接按Alt+F6即可

測試函式
@Test來標註測試函式
在測試中常用的語句如下:
fail( 資訊 ); //表示程式出錯
assertEqauls(引數1,引數2 ); //表示程式要保證兩個引數要相等
assertNull(引數); //表示引數要為null

     @Test 
     public void testSum2() { 
      HelloWorld a = new HelloWorld();  
      assertEquals(a.sum(0, 100), 100); 
      // fail("Not yet implemented"); 
      }

4. 程式的除錯

程式中的錯誤
程式中的錯誤通常可以分成三大類
語法錯誤(Syntax error)
編輯、編譯器發現
執行錯誤(Runtime error)
異常處理機制
邏輯錯誤(Logic error)
除錯(debug) 、單元測試(unit test)

程式的除錯(debug)
在IDE中,專案上點右鍵 ,debug as…
進入到除錯檢視(debug perspective)

除錯的三種手段
斷點 (breakpoint)
跟蹤 (trace)
監視 (watch)

斷點
切換斷點(toggle breakpoint )
用滑鼠單擊(或右擊)編輯器左邊條
或者
Eclipse Ctrl+Shift+B
NetBeans Ctrl+F8

跟蹤

Eclipse NetBeans
逐語句執行 F5 F7
逐過程執行 F6 F8
跳出函式 F7 Ctrl+F7
執行到游標處 Ctrl+R F4

監視

即時監視
滑鼠指向變數

快速監視
點右鍵,Inspector

新增監視
點右鍵,Watch

還可以看:呼叫堆疊等等