一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java 常用類解析:java異常機制,異常棧,異常處理方式,異常鏈,異常丟失詳解

Java 常用類解析:java異常機制,異常棧,異常處理方式,異常鏈,異常丟失詳解

2020-08-28 10:21Java教程網 Java教程

這篇文章主要介紹了Java 常用類解析:java異常機制,異常棧,異常處理方式,異常鏈,異常丟失詳解的相關資料,需要的朋友可以參考下

1、java標準異常概述

Throwable表示任何可以作為異常被拋出的類,有兩個子類Error和Exception。從這兩個類的源代碼中可以看出,這兩個類并沒有添加新的方法,Throwable提供了所以方法的實現。Error表示編譯時和系統錯誤。Exception是可以被拋出的異常類。RuntimeException繼承自Exception(如NullPointerException),表示運行時異常,JVM會自動拋出.

2、自定義異常類

自定義異常類方法: 通過繼承Throwable或Exception。異常類的所有實現都是基類Throwable實現的,所以構造自定義異常類完全可以參考Exception和Error類。我們只要添加上自定義異常類的構造方法就可以了

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<span style="font-size:16px;">package demo.others;
 
/**
 * 自定義異常類方法
 * 1、通過繼承Throwable
 * 2、通過繼承Exception
 *
 * @author Touch
 */
public class MyExceptionDemo extends Exception {
 
 private static final long serialVersionUID = 1L;
 
 public MyExceptionDemo() {
  super();
 }
 
 public MyExceptionDemo(String message) {
  super(message);
 }
 
 public MyExceptionDemo(String message, Throwable cause) {
  super(message, cause);
 }
 
 public MyExceptionDemo(Throwable cause) {
  super(cause);
 }
}
</span>

 3、異常棧及異常處理方式

可以通過try、catch來捕獲異常。捕獲到的異常。下面的示例演示了幾種常用異常處理方式

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<span style="font-size:16px;">package demo.others;
 
import mine.util.exception.MyException;
 
public class ExceptionDemo1 {
 public void f() throws MyException {
  throw new MyException("自定義異常");
 }
 
 public void g() throws MyException {
  f();
 }
 
 public void h() throws MyException {
  try {
   g();
  } catch (MyException e) {
   //1、通過獲取棧軌跡中的元素數組來顯示異常拋出的軌跡
   for (StackTraceElement ste : e.getStackTrace())
    System.out.println(ste.getMethodName());
   //2、直接將異常棧信息輸出至標準錯誤流或標準輸出流
   e.printStackTrace();//輸出到標準錯誤流
   e.printStackTrace(System.err);
   e.printStackTrace(System.out);
   //3、將異常信息輸出到文件中
   //e.printStackTrace(new PrintStream("file/exception.txt"));
   //4、重新拋出異常,如果直接拋出那么棧路徑是完整的,如果用fillInStackTrace()
   //那么將會從這個方法(當前是h()方法)作為異常發生的原點。
   //throw e;
   throw (MyException)e.fillInStackTrace();
  }
 }
 public static void main(String[] args) {
   try {
    new ExceptionDemo1().h();
   } catch (MyException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
 }
}
</span>

運行結果:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
f
g
h
main
mine.util.exception.MyException: 自定義異常
 at demo.others.ExceptionDemo1.f(ExceptionDemo1.Java:7)
 at demo.others.ExceptionDemo1.g(ExceptionDemo1.Java:11)
 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)
 at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
mine.util.exception.MyException: 自定義異常
 at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)
 at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)
 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)
 at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
mine.util.exception.MyException: 自定義異常
 at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)
 at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)
 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)
 at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
mine.util.exception.MyException: 自定義異常
 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:30)
 at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)

分析上面的程序,首先main函數被調用,然后是調用h函數,再g函數、f函數,f函數拋出異常,并在h函數捕獲,這時將依次從棧頂到棧底輸出異常棧路徑。

4、異常鏈

有時候我們會捕獲一個異常后在拋出另一個異常,如下代碼所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<span style="font-size:16px;">package demo.others;
 
import java.io.IOException;
 
import mine.util.exception.MyException;
 
public class ExceptionDemo2 {
 public void f() throws MyException {
  throw new MyException("自定義異常");
 }
 
 public void g() throws Exception {
  try {
   f();
  } catch (MyException e) {
   e.printStackTrace();
   throw new Exception("重新拋出的異常1");
  }
 }
 
 public void h() throws IOException {
  try {
   g();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   throw new IOException("重新拋出異常2");
  }
 }
 public static void main(String[] args) {
   try {
    new ExceptionDemo2().h();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
 }
}
</span>

運行結果:

?
1
2
3
4
5
6
7
8
9
10
11
12
mine.util.exception.MyException: 自定義異常
 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)
java.lang.Exception: 重新拋出的異常1
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)
java.io.IOException: 重新拋出異常2
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)

從結果中我們可以看出,異常棧變小了。也就是說丟失了最原始的異常信息。怎樣保存最原始的異常信息呢?Throwable類中有個Throwable  cause屬性,表示原始異常。通過接收cause參數的構造器可以把原始異常傳遞給新異常,或者通過initCause()方法。如下示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<span style="font-size:16px;">package demo.others;
 
import java.io.IOException;
 
import mine.util.exception.MyException;
 
public class ExceptionDemo2 {
 public void f() throws MyException {
  throw new MyException("自定義異常");
 }
 
 public void g() throws Exception {
  try {
   f();
  } catch (MyException e) {
   e.printStackTrace();
   throw new Exception("重新拋出的異常1",e);
  }
 }
 
 public void h() throws IOException {
  try {
   g();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   IOException io=new IOException("重新拋出異常2");
   io.initCause(e);
   throw io;
  }
 }
 public static void main(String[] args) {
   try {
    new ExceptionDemo2().h();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
 }
}
</span>

 結果:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mine.util.exception.MyException: 自定義異常
 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)
java.lang.Exception: 重新拋出的異常1
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)
Caused by: mine.util.exception.MyException: 自定義異常
 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
 ... 2 more
java.io.IOException: 重新拋出異常2
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)
Caused by: java.lang.Exception: 重新拋出的異常1
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 ... 1 more
Caused by: mine.util.exception.MyException: 自定義異常
 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
 ... 2 more

從結果中看出當獲取到“重新拋出異常2的時候,同時可以輸出原始異常“重新拋出的異常1“和原始異常”自定義異常,這就是異常鏈。

5、finally的使用

finally子句總是執行的,通常用來做一些清理工作,如關閉文件,關閉連接等

下面舉幾個finally的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<span style="font-size:16px;">// 讀取指定路徑文本文件
 public static String read(String filePath) {
  StringBuilder str = new StringBuilder();
  BufferedReader in = null;
  try {
   in = new BufferedReader(new FileReader(filePath));
   String s;
   try {
    while ((s = in.readLine()) != null)
     str.append(s + '\n');
   } finally {
    in.close();
   }
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return str.toString();
 }</span>

分析:如果調用in = new BufferedReader(new FileReader(filePath));時發生異常,這時是一個文件路徑不存在的異常,也就是說并沒有打開文件,這時將會直接跳到catch塊,而不會執行try...finally塊(并不是finally子句)里面的語句in.close();此時不需要關閉文件。

再看一個例子,會導致異常的丟失

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<span style="font-size:16px;">package demo.others;
 
import mine.util.exception.MyException;
 
public class ExceptionDemo3 {
 public void f() throws MyException {
  throw new MyException("異常1");
 }
 
 public void g() throws MyException {
  throw new MyException("異常2");
 }
 
 public static void main(String[] args) {
 
  try {
   ExceptionDemo3 ex = new ExceptionDemo3();
   try {
    ex.f();
   } finally {
    ex.g();//此時捕獲g方法拋出的異常,f方法拋出的異常丟失了
   }
  } catch (MyException e) {
   System.out.println(e);
  }
 
 }
}
</span>

結果:mine.util.exception.MyException: 異常2

此時異常1就丟失了

或者這樣寫:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<span style="font-size:16px;">package demo.others;
 
import mine.util.exception.MyException;
 
public class ExceptionDemo3 {
 
 public void g() throws MyException {
  throw new MyException("異常2");
 }
 
 public static void main(String[] args) {
  ExceptionDemo3 ex = new ExceptionDemo3();
  try {
   ex.g();
  } finally {
   //直接return會丟失所以拋出的異常
   return;
  }
 
 }
}
</span>

6、異常的限制

(1)當覆蓋方法時,只能拋出在基類方法的異常說明里列出的那些異常,有些基類的方法聲明拋出異常其實并沒有拋出異常,這是因為可能在其子類的覆蓋方法中會拋出異常

(2)構造器可以拋出任何異常而不必理會基類構造器所拋出的異常,派生類構造器異常說明必須包含基類構造器異常說明,因為構造派生類對象時會調用基類構造器。此外,派生類構造器不能捕獲基類構造器拋出的異常。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 青草娱乐极品免费视频 | 91av爱爱| 99re这里只有精品视频 | 俄罗斯三级完整版在线观看 | 黑人巨大和日本娇小中出 | 日本特级大片 | 垫底辣妹免费观看完整版 | 亚洲天堂免费观看 | www黄| 国内精品一区二区在线观看 | tubehdxx丝袜正片| 国产精品久久毛片蜜月 | 亚洲天堂v | 亚洲性久久久影院 | 国产精品久久久久无毒 | 青青青在线免费 | 日本一在线中文字幕天堂 | 精品国产免费 | 国产巨大bbbb俄罗斯 | 动漫美女人物被黄漫在线看 | 精品国产影院 | 日本视频中文字幕 | 99久久一区二区精品 | 日本在线播放视频 | 国产在线精品香蕉综合网一区 | 国产亚洲高清国产拍精品 | 国产卡一卡二卡三卡四 | 4399h漫画| 黑人又大又硬又粗再深一点 | 日韩亚洲国产激情在线观看 | 鬼畜重口高h合集长短篇 | 日韩一区二三区无 | 男人晚上适合偷偷看的污污 | 美女福利网站 | 久久视频在线视频观看精品15 | 色综合九九 | 91这里只有精品 | 99超级碰碰成人香蕉网 | 日本三级免费网站 | 四虎国产成人免费观看 | 无人区在线观看免费视频国语 |