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

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

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产亚洲综合久久 | 欧美18-19sex性处 | 99久久精品久久久久久清纯 | 欧美综合在线 | 国产欧美另类久久精品91 | 免费的强动漫人物的 | 欧美性高清另类videosex死尸 | 我的好妈妈7中字在线观看韩国 | 30分钟的高清视频在线观看 | 天堂8在线天堂资源bt | 久久亚洲成a人片 | 久久精品国产免费播高清无卡 | 亚洲天堂视频在线播放 | 91精品啪在线观看国产老湿机 | 日本免费高清在线观看播放 | sese在线观看 | 国内亚州视频在线观看 | 国产综合成色在线视频 | 99在线免费观看视频 | 欧美贵妇videos办公室360 | 操骚0| 国产99热| 半挠脚心半黄的网站 | 日本伦理动漫在线观看 | 亚洲干综合 | 久久久精品日本一区二区三区 | 手机av| 继攵催眠女乱h调教 | 国产精品成人扳一级aa毛片 | 国产日产国无高清码2020 | 9999视频 | 美女被扒开屁股进去网 | 亚洲欧美精品一区天堂久久 | 亚洲国产精品成人综合久久久 | 情侣宾馆愉拍自拍视频 | 免费大片| 日本妇人成熟免费观看18 | 免费a视频在线观看 | 白鹿扒开内裤露出尿孔 | 大胸孕妇孕交pregnantsex 大象视频污 | 亚洲AV无码国产精品色午夜情 |