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


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

看以下例子:

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");

按照提示修改之后:

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()方法。

因此作出如下修改:

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")並不會執行。

從上面的例子中可以看出,使用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,所以出錯。

搜索微信公眾號“程序員考拉”,歡迎關注!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM