Java 異常的處理方式--throws和try catch

異常的第一種處理方式throws。java

看如下例子:程序員

import java.io.*;
public class ExceptionTest04{
 public static void main(String[] args){
   m1(); 
 }
 public static void  m1(){
   m2();
 }
 public static void m2(){
   m3();
 }
 public static void m3(){
   new FileInputStream("c:/ab.txt");  //FileInputStream構造方法聲明位置上使用throws(向上拋)
  }
}

以上代碼編譯時出錯:微信

ExceptionTest04.java:16: 錯誤: 未報告的異常錯誤FileNotFoundException; 必須對其進行捕獲或聲明以便拋出
                new FileInputStream("c:/ab.txt");

按照提示修改以後:spa

import java.io.*;
public class ExceptionTest04{
 public static void main(String[] args){
   m1(); 
   System.out.println("hello");
 }
 public static void m1(){
   m2();
 }
 public static void m2(){
   m3();
 }
 public static void m3() throws FileNotFoundException{
   new FileInputStream("c:/ab.txt");
 }
}

編譯時出錯;調試

ExceptionTest04.java:30: 錯誤: 未報告的異常錯誤FileNotFoundException; 必須對其進行捕獲或聲明以便拋出
             m3();

由此看出,修改以後m3()運行時出現錯誤,上拋給m2(),以此類推,m2()上拋異常給m1(),m1()上拋異常給main()方法。code

所以做出以下修改:對象

import java.io.*;
public class ExceptionTest04{
 public static void main(String[] args) throws FileNotFoundException{
   m1(); 
   System.out.println("hello");
 }
 public static void m1() throws FileNotFoundException{
   m2();
 }
 public static void m2() throws FileNotFoundException{
   m3();
 }
 public static void m3() throws FileNotFoundException{
   new FileInputStream("c:/ab.txt");
 }
}

修改以後編譯經過,可是System.out.println("hello")並不會執行。blog

從上面的例子中能夠看出,使用throws處理異常不是真正處理異常而是推卸責任,誰調用就會拋給誰。上面的m1方法若是出現了異常,由於採用的是上拋,JVM遇到這個異常就會退出JVM,以後的代碼不會執行。所以引入try...catch...方法。修改以下,編譯運行經過,而且輸出:hello。繼承

import java.io.*;
public class ExceptionTest04{
 public static void main(String[] args) throws FileNotFoundException{
   try{
     m1();
   }  catch(FileNotFoundException e){}
   System.out.println("hello");
 }
 public static void m1() throws FileNotFoundException{
   m2();
 }
 public static void m2() throws FileNotFoundException{
   m3();
 }
 public static void m3() throws FileNotFoundException{
   new FileInputStream("c:/ab.txt");
 }
}

捕捉   try...catch...事件

先來看看語法,

try{

可能出現異常的代碼;

}catch(異常類型1 變量){

處理異常的代碼;

}catch(異常類型2 變量){

    處理異常的代碼;

}......

 

看如下例子:

import java.io.*;
public class ExceptionTest05{
 public static void main(String[] args){
   try{
     //FileNotFoundException
     FileInputStream fis=new FileInputStream("c:/ab.txt");
   }catch(ArithmeticException e){  //捕獲的異常是算術異常  
   }  
 }  
}

以上的代碼編譯沒法經過,由於FileNotFoundException沒有處理,報錯:

ExceptionTest05.java:19: 錯誤: 未報告的異常錯誤FileNotFoundException; 必須對其進行捕獲或聲明以便拋出
                        FileInputStream fis=new FileInputStream("c:/ab.txt");
                                           ^
1 個錯誤

也就是說可能出現異常的代碼和捕獲異常的代碼必須是相對應的。

將捕獲的異常修改以後,編譯經過,

import java.io.*;
public class ExceptionTest05{
 public static void main(String[] args){
   try{
     //FileNotFoundException
     FileInputStream fis=new FileInputStream("c:/ab.txt");
   }catch(FileNotFoundException e){    
   }  
 }  
}

再看如下例子,如下程序編譯沒法經過,

import java.io.*;
public class ExceptionTest05{
 public static void main(String[] args){
   try{
     //FileNotFoundException
     FileInputStream fis=new FileInputStream("c:/ab.txt");
     fis.read();
   }catch(FileNotFoundException e){    
   }
 }  
}

報錯:

ExceptionTest05.java:48: 錯誤: 未報告的異常錯誤IOException; 必須對其進行捕獲或聲明以便拋出
                        fis.read();
                               ^
1 個錯誤

由於read()方法又拋出了IOException的異常,而catch()只處理了FileNotFoundException的異常。

read()方法的拋出的異常以下圖所示:

 

要想編譯經過,必選進行IOException處理,

import java.io.*;
public class ExceptionTest05{
 public static void main(String[] args){
   try{
     //FileNotFoundException
     FileInputStream fis=new FileInputStream("c:/ab.txt");
     fis.read();
   }catch(FileNotFoundException e){    
   }catch(IOException e){
   }
 }  
}

或者以下直接進行IOException處理,這是由於FileNotFoundException繼承IOException。

import java.io.*;
public class ExceptionTest05{
 public static void main(String[] args){
   try{
     //FileNotFoundException
     FileInputStream fis=new FileInputStream("c:/ab.txt");
     fis.read();
   }catch(IOException e){
   }
 }  
}

再看如下例子:

import java.io.*;
public class ExceptionTest05{
 public static void main(String[] args){
   try{
     //FileNotFoundException
     FileInputStream fis=new FileInputStream("c:/ab.txt");
     fis.read();
   }catch(IOException e){    
   }catch(FileNotFoundException e){
   }
 }  
}

 編譯出錯:

ExceptionTest05.java:97: 錯誤: 已捕獲到異常錯誤FileNotFoundException
               }catch(FileNotFoundException e){
                ^
1 個錯誤

這是由於FileNotFoundException繼承IOException,catch語句塊雖然能夠寫多個,可是從上到下catch,必須從小類型異常到大類型異常進行捕捉。而且try...catch...中最多執行一個catch語句塊,執行結束後,try...catch...就執行結束了。

最後看一個詳細的例子總結一下以前的內容。

import java.io.*;
public class ExceptionTest06{
 public static void main(String[] args){
   FileInputStream fis=new FileInputStream("abc");
   fis.read();
 }
}

以上程序編譯沒法經過,能夠進行以下處理,

import java.io.*;
public class ExceptionTest06{
 public static void main(String[] args)throws IOException,FileNotFoundException{
   FileInputStream fis=new FileInputStream("c:/ab.txt");
   fis.read();
 }
}

 或者進行以下處理:

import java.io.*;
public class ExceptionTest06{
 public static void main(String[] args)throws IOException{
   FileInputStream fis=new FileInputStream("c:/ab.txt");
   fis.read();
 }
}

或者使用try...catch...進行異常處理。

import java.io.*;
public class ExceptionTest06{
 public static void main(String[] args){
   try{
   FileInputStream fis=new FileInputStream("c:/ab.txt");
   fis.read();
   }catch(FileNotFoundException e){   //e內存地址指向的堆中的那個對象是FileNotFoundException類型的事件。
      System.out.println("讀取的文件不存在!");
   }catch(IOException e){
     System.out.println("其它IO異常!");
   }
   System.out.println("ABC");
 }
}

運行以後輸出:

讀取的文件不存在!
ABC
 

如何取得異常對象的具體信息,經常使用的方法主要有兩種:

取得異常信息描述:getMessage()

取得異常的堆棧信息(比較適合於程序調試階段):printStackTrace();

先看取得異常的堆棧信息printStackTrace()方法。看如下例子。

import java.io.*;
public class ExceptionTest07{
 public static void main(String[] args){
   try{
     FileInputStream fis = new FileInputStream("c:/ab.txt");
   }catch(FileNotFoundException e){
     //打印異常堆棧信息
     //通常狀況下都會使用該方式去調試程序
     e.printStackTrace();
   }
   //這段代碼會執行
   System.out.println("ABC");
 }
}

 編譯運行後輸出:

java.io.FileNotFoundException: c:\ab.txt (系統找不到指定的文件。)
       at java.io.FileInputStream.open0(Native Method)
       at java.io.FileInputStream.open(Unknown Source)
       at java.io.FileInputStream.<init>(Unknown Source)
       at java.io.FileInputStream.<init>(Unknown Source)
       at ExceptionTest07.main(ExceptionTest07.java:8)
ABC

再來看取得異常信息描述:getMessage()方法。

import java.io.*;
public class ExceptionTest07{
 public static void main(String[] args){
   try{
     FileInputStream fis = new FileInputStream("c:/ab.txt");
   }catch(FileNotFoundException e){
      msg=e.getMessage();
     System.out.println(msg);
   }
   System.out.println("ABC");
 }
}

編譯運行後輸出:

c:\ab.txt (系統找不到指定的文件。)
ABC

從上面的例子能夠看出,e.printStackTrace()比e.getMessage()的方法詳細,前者輸出的異常信息比後者完整,所以通常使用e.printStackTrace()來打印異常信息。捕捉了異常以後進行打印才能知道你的代碼哪裏出現了異常,才能不斷地去修改完善本身的代碼,也就是所說的通常使用e.printStackTrace()去調試程序。 

接下來再補充一下方法的重寫與異常的知識。

這塊兒內容只要記着一個原則:重寫的方法不能比被重寫的方法拋出更寬泛的異常。結合如下例子來理解一下。

class A{
 public void m1(){}
}
public class AB extends A{
 //子類永遠沒法比父類拋出更寬泛的異常
 public void m1() throws Exception{}
}

上述代碼編譯運行後出錯:

AB.java:5: 錯誤: AB中的m1()沒法覆蓋A中的m1()
       public void m1() throws Exception{}
                   ^
 被覆蓋的方法未拋出Exception
1 個錯誤

這是由於子類永遠沒法比父類拋出更寬泛的異常。再看一個例子:

import java.io.*;
class A{
 public void m1()throws FileNotFoundException{}
}
public class AB extends A{
 public void m1()throws IOException{}
}

編譯運行後出錯:

AB.java:22: 錯誤: AB中的m1()沒法覆蓋A中的m1()
       public void m1()throws IOException{}
                   ^
 被覆蓋的方法未拋出IOException
1 個錯誤

父類中的m1()方法拋出FileNotFoundException異常,AB繼承A,而且重寫m1()方法,拋出IOException的異常,而咱們知道,FileNotFoundException繼承IOException,因此出錯。

搜索微信公衆號「程序員考拉」,歡迎關注!

相關文章
相關標籤/搜索