異常的第一種處理方式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,因此出錯。
搜索微信公衆號「程序員考拉」,歡迎關注!