国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

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

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

服務器之家 - 編程語言 - Java教程 - java異常(Exception)處理機制詳解

java異常(Exception)處理機制詳解

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

這篇文章主要介紹了java異常(Exception)處理機制詳解的相關資料,主要介紹異常的定義及使用方法,需要的朋友可以參考下

一. 異常的定義

在《Java編程思想》中這樣定義 異常:阻止當前方法或作用域繼續執行的問題。雖然java中有異常處理機制,但是要明確一點,決不應該用"正常"的態度來看待異常。絕對一點說異常就是某種意義上的錯誤,就是問題,它可能會導致程序失敗。之所以java要提出異常處理機制,就是要告訴開發人員,你的程序出現了不正常的情況,請注意。

記得當初學習java的時候,異??偸歉悴惶宄?,不知道這個異常是什么意思,為什么會有這個機制?但是隨著知識的積累逐漸也對異常有一點感覺了。舉一個例子來說明一下異常的用途。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Calculator
 {
  public int devide(int num1,
int num2)
 {
    //判斷除數是否為0
    if(num2
 == 0)
 {
      throw new IllegalArgumentException("除數不能為零");
    }
     
    return num1/num2;
  }
}

 看一下這個類中關于除運算的方法,如果你是新手你可能會直接返回計算結果,根本不去考慮什么參數是否正確,是否合法(當然可以原諒,誰都是這樣過來的)。但是我們應盡可能的考慮周全,把可能導致程序失敗的"苗頭"扼殺在搖籃中,所以進行參數的合法性檢查就很有必要了。其中執行參數檢查拋出來的那個參數非法異常,這就屬于這個方法的不正常情況。正常情況下我們會正確的使用計算器,但是不排除粗心大意把除數賦值為0。如果你之前沒有考慮到這種情況,并且恰巧用戶數學基礎不好,那么你完了。但是如果你之前考慮到了這種情況,那么很顯然錯誤已在你的掌控之中。

 二. 異常掃盲行動

今天和別人聊天時看到一個笑話:世界上最真情的相依,是你在try我在catch。無論你發神馬脾氣,我都默默承受,靜靜處理。 大多數新手對java異常的感覺就是:try...catch...。沒錯,這是用的最多的,也是最實用的。我的感覺就是:java異常是從"try...catch..."走來。

 首先來熟悉一下java的異常體系:

 Throwable 類是 Java 語言中所有錯誤或異常的超類(這就是一切皆可拋的東西)。它有兩個子類:Error和Exception。

 Error:用于指示合理的應用程序不應該試圖捕獲的嚴重問題。這種情況是很大的問題,大到你不能處理了,所以聽之任之就行了,你不用管它。比如說VirtualMachineError:當 Java 虛擬機崩潰或用盡了它繼續操作所需的資源時,拋出該錯誤。好吧,就算這個異常的存在了,那么應該何時,如何處理它呢??交給JVM吧,沒有比它更專業的了。 

Exception:它指出了合理的應用程序想要捕獲的條件。Exception又分為兩類:一種是CheckedException,一種是UncheckedException。這兩種Exception的區別主要是CheckedException需要用try...catch...顯示的捕獲,而UncheckedException不需要捕獲。通常UncheckedException又叫做RuntimeException?!秂ffective java》指出:對于可恢復的條件使用被檢查的異常(CheckedException),對于程序錯誤(言外之意不可恢復,大錯已經釀成)使用運行時異常(RuntimeException)。

我們常見的RuntimeExcepiton有IllegalArgumentException、IllegalStateException、NullPointerException、IndexOutOfBoundsException等等。對于那些CheckedException就不勝枚舉了,我們在編寫程序過程中try...catch...捕捉的異常都是CheckedException。io包中的IOException及其子類,這些都是CheckedException。

 三. 異常的使用

在異常的使用這一部分主要是演示代碼,都是我們平常寫代碼的過程中會遇到的(當然只是一小部分),拋磚引玉嗎!

例1. 這個例子主要通過兩個方法對比來演示一下有了異常以后代碼的執行流程。

?
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
public static void testException1()
 {
    int[]
 ints = new int[]
 { 1,
2,
3,
4 };
    System.out.println("異常出現前");
    try {
      System.out.println(ints[4]);
      System.out.println("我還有幸執行到嗎");//
 發生異常以后,后面的代碼不能被執行
    }
catch (IndexOutOfBoundsException
 e) {
      System.out.println("數組越界錯誤");
    }
    System.out.println("異常出現后");
  }
  /*output:
  異常出現前
  數組越界錯誤
  4
  異常出現后
  */

  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void testException2()
 {
    int[]
 ints = new int[]
 { 1,
2,
3,
4 };
    System.out.println("異常出現前");
    System.out.println(ints[4]);
    System.out.println("我還有幸執行到嗎");//
 發生異常以后,他后面的代碼不能被執行
  }

  首先指出例子中的不足之處,IndexOutofBoundsException是一個非受檢異常,所以不用try...catch...顯示捕捉,但是我的目的是對同一個異常用不同的處理方式,看它會有什么不同的而結果(這里也就只能用它將就一下了)。異常出現時第一個方法只是跳出了try塊,但是它后面的代碼會照樣執行的。但是第二種就不一樣了直接跳出了方法,比較強硬。從第一個方法中我們看到,try...catch...是一種"事務性"的保障,它的目的是保證程序在異常的情況下運行完畢,同時它還會告知程序員程序中出錯的詳細信息(這種詳細信息有時要依賴于程序員設計)。

例2. 重新拋出異常

?
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
public class Rethrow
 {
  public static void readFile(String
 file) throws FileNotFoundException
 {
    try {
      BufferedInputStream
 in = new BufferedInputStream(new FileInputStream(file));
    }
catch (FileNotFoundException
 e) {
      e.printStackTrace();
      System.err.println("不知道如何處理該異?;蛘吒静幌胩幚硭遣蛔鎏幚碛植缓线m,這是重新拋出異常交給上一級處理");
      //重新拋出異常
      throw e;
    }
  }
   
  public static void printFile(String
 file) {
    try {
      readFile(file);
    }
catch (FileNotFoundException
 e) {
      e.printStackTrace();
    }
  }
   
  public static void main(String[]
 args) {
    printFile("D:/file");
  }
}

  異常的本意是好的,讓我們試圖修復程序,但是現實中我們修復的幾率很小,我們很多時候就是用它來記錄出錯的信息。如果你厭倦了不停的處理異常,重新拋出異常對你來說可能是一個很好的解脫。原封不動的把這個異常拋給上一級,拋給調用這個方法的人,讓他來費腦筋吧。這樣看來,java異常(當然指的是受檢異常)又給我們平添很多麻煩,盡管它的出發點是好的。

例3. 異常鏈的使用及異常丟失

定義三個異常類:ExceptionA,ExceptionB,ExceptionC

 

?
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
public class ExceptionA
extends Exception
 {
  public ExceptionA(String
 str) {
    super();
  }
}
 
public class ExceptionB
extends ExceptionA
 {
 
  public ExceptionB(String
 str) {
    super(str);
  }
}
 
public class ExceptionC
extends ExceptionA
 {
  public ExceptionC(String
 str) {
    super(str);
  }
}

異常丟失的情況:

?
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
public class NeverCaught
 {
  static void f()
throws ExceptionB{
    throw new ExceptionB("exception
 b");
  }
 
  static void g()
throws ExceptionC
 {
    try {
      f();
    }
catch (ExceptionB
 e) {
      ExceptionC
 c = new ExceptionC("exception
 a");
      throw c;
    }
  }
 
  public static void main(String[]
 args) {
      try {
        g();
      }
catch (ExceptionC
 e) {
        e.printStackTrace();
      }
  }
 
}
/*
exception.ExceptionC
at
 exception.NeverCaught.g(NeverCaught.java:12)
at
 exception.NeverCaught.main(NeverCaught.java:19)
*/

為什么只是打印出來了ExceptionC而沒有打印出ExceptionB呢?這個還是自己分析一下吧!

上面的情況相當于少了一種異常,這在我們排錯的過程中非常的不利。那我們遇到上面的情況應該怎么辦呢?這就是異常鏈的用武之地:保存異常信息,在拋出另外一個異常的同時不丟失原來的異常。

?
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
43
44
45
46
47
48
49
50
51
52
public class NeverCaught
 {
  static void f()
throws ExceptionB{
    throw new ExceptionB("exception
 b");
  }
 
  static void g()
throws ExceptionC
 {
    try {
      f();
    }
catch (ExceptionB
 e) {
      ExceptionC
 c = new ExceptionC("exception
 a");
      //異常連
      c.initCause(e);
      throw c;
    }
  }
 
  public static void main(String[]
 args) {
      try {
        g();
      }
catch (ExceptionC
 e) {
        e.printStackTrace();
      }
  }
 
}
/*
exception.ExceptionC
at
 exception.NeverCaught.g(NeverCaught.java:12)
at
 exception.NeverCaught.main(NeverCaught.java:21)
Caused
 by: exception.ExceptionB
at
 exception.NeverCaught.f(NeverCaught.java:5)
at
 exception.NeverCaught.g(NeverCaught.java:10)
...
 1 more
*/

這個異常鏈的特性是所有異常均具備的,因為這個initCause()方法是從Throwable繼承的。

例4. 清理工作

清理工作對于我們來說是必不可少的,因為如果一些消耗資源的操作,比如IO,JDBC。如果我們用完以后沒有及時正確的關閉,那后果會很嚴重,這意味著內存泄露。異常的出現要求我們必須設計一種機制不論什么情況下,資源都能及時正確的清理。這就是finally。

?
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
public void readFile(String
 file) {
    BufferedReader
 reader = null;
    try {
      reader
 = new BufferedReader(new InputStreamReader(
          new FileInputStream(file)));
      //
 do some other work
    }
catch (FileNotFoundException
 e) {
      e.printStackTrace();
    }
finally {
      try {
        reader.close();
      }
catch (IOException
 e) {
        e.printStackTrace();
      }
    }
  }

例子非常的簡單,是一個讀取文件的例子。這樣的例子在JDBC操作中也非常的常見。(所以,我覺得對于資源的及時正確清理是一個程序員的基本素質之一。)

Try...finally結構也是保證資源正確關閉的一個手段。如果你不清楚代碼執行過程中會發生什么異常情況會導致資源不能得到清理,那么你就用try對這段"可疑"代碼進行包裝,然后在finally中進行資源的清理。舉一個例子:

?
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
public void readFile()
 {
    BufferedReader
 reader = null;
    try {
      reader
 = new BufferedReader(new InputStreamReader(
          new FileInputStream("file")));
      //
 do some other work
     
      //close
 reader
      reader.close();
    }
catch (FileNotFoundException
 e) {
      e.printStackTrace();
    }
catch (IOException
 e) {
      e.printStackTrace();
    }
  }

我們注意一下這個方法和上一個方法的區別,下一個人可能習慣更好一點,及早的關閉reader。但是往往事與愿違,因為在reader.close()以前異常隨時可能發生,這樣的代碼結構不能預防任何異常的出現。因為程序會在異常出現的地方跳出,后面的代碼不能執行(這在上面應經用實例證明過)。這時我們就可以用try...finally來改造:

?
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
public void readFile()
 {
    BufferedReader
 reader = null;
    try {
      try {
        reader
 = new BufferedReader(new InputStreamReader(
            new FileInputStream("file")));
        //
 do some other work
 
        //
 close reader
      }
finally {
        reader.close();
      }
    }
catch (FileNotFoundException
 e) {
      e.printStackTrace();
    }
catch (IOException
 e) {
      e.printStackTrace();
    }
  }

及早的關閉資源是一種良好的行為,因為時間越長你忘記關閉的可能性越大。這樣在配合上try...finally就保證萬無一失了(不要嫌麻煩,java就是這么中規中矩)。

再說一種情況,假如我想在構造方法中打開一個文件或者創建一個JDBC連接,因為我們要在其他的方法中使用這個資源,所以不能在構造方法中及早的將這個資源關閉。那我們是不是就沒轍了呢?答案是否定的??匆幌孪旅娴睦樱?/p>

?
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
public class ResourceInConstructor
 {
  BufferedReader
 reader = null;
  public ResourceInConstructor()
 {
    try {
      reader
 = new BufferedReader(new InputStreamReader(new FileInputStream("")));
    }
catch (FileNotFoundException
 e) {
      e.printStackTrace();
    }
  }
   
  public void readFile()
 {
    try {
      while(reader.readLine()!=null)
 {
        //do
 some work
      }
    }
catch (IOException
 e) {
      e.printStackTrace();
    }
  }
   
  public void dispose()
 {
    try {
      reader.close();
    }
catch (IOException
 e) {
      e.printStackTrace();
    }
  }
}

這一部分講的多了一點,但是異常確實是看起來容易用起來難的東西呀,java中還是有好多的東西需要深挖的。

四. 異常的誤用

對于異常的誤用著實很常見,上一部分中已經列舉了幾個,大家仔細的看一下。下面再說兩個其他的。

例1. 用一個Exception來捕捉所有的異常,頗有"一夫當關萬夫莫開"的氣魄。不過這也是最傻的行為。

?
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
public void readFile(String
 file) {
    BufferedReader
 reader = null;
    Connection
 conn = null;
    try {
      reader
 = new BufferedReader(new InputStreamReader(
          new FileInputStream(file)));
      //
 do some other work
       
      conn
 = DriverManager.getConnection("");
      //...
    }
catch (Exception
 e) {
      e.printStackTrace();
    }
finally {
      try {
        reader.close();
        conn.close();
      }
catch (Exception
 e) {
        e.printStackTrace();
      }
    }
  }

  從異常角度來說這樣嚴格的程序確實是萬無一失,所有的異常都能捕獲。但是站在編程人員的角度,萬一這個程序出錯了我們該如何分辨是到底是那引起的呢,IO還是JDBC...所以,這種寫法很值得當做一個反例。大家不要以為這種做法很幼稚,傻子才會做。我在公司實習時確實看見了類似的情況:只不過是人家沒有用Exception而是用了Throwable。

例2. 這里就不舉例子了,上面的程序都是反例。異常是程序處理意外情況的機制,當程序發生意外時,我們需要盡可能多的得到意外的信息,包括發生的位置,描述,原因等等。這些都是我們解決問題的線索。但是上面的例子都只是簡單的printStackTrace()。如果我們自己寫代碼,就要盡可能多的對這個異常進行描述。比如說為什么會出現這個異常,什么情況下會發生這個異常。如果傳入方法的參數不正確,告知什么樣的參數是合法的參數,或者給出一個sample。

例3. 將try block寫的簡短,不要所有的東西都扔在這里,我們盡可能的分析出到底哪幾行程序可能出現異常,只是對可能出現異常的代碼進行try。盡量為每一個異常寫一個try...catch,避免異常丟失。在IO操作中,一個IOException也具有"一夫當關萬夫莫開"的氣魄。

五.總結

總結非常簡單,不要為了使用異常而使用異常。異常是程序設計的一部分,對它的設計也要考究點。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美午夜精品久久久久久蜜 | 亚洲精品日韩精品 | 亚洲综合在线视频 | 天堂一区 | 成人一区二区三区在线观看 | 中文字幕在线永久在线视频 | 亚洲天堂免费在线 | 亚洲精品久久久久久久久久久 | 日韩码有限公司在线观看 | 成人精品| 成人爽a毛片一区二区免费 日韩av高清在线 | 国产伦精品一区二区三区四区视频_ | 日韩在线免费 | 日本在线观看一区 | 久久久久久久久久久久99 | 日本三级中文在线电影 | 高清免费av | 黄色高清视频在线观看 | 日本久久久久久 | 国产精品视频网 | 2018自拍偷拍 | 国产精品久久久久久久久 | 国产精品久久久久久亚洲调教 | 国产精品亚洲一区二区三区 | 久久免费99精品久久久久久 | 久在线草 | 久久中文字幕一区二区三区 | 91麻豆精品国产91久久久资源速度 | 国产麻豆乱码精品一区二区三区 | 日本天堂在线 | 国产精品久久久久久久久久东京 | 91毛片视频 | 国产福利一区二区三区四区 | 亚洲精品久久久久久久久久久 | 中日韩午夜理伦电影免费 | 久久久中文| 午夜av在线| 欧美视频在线一区 | 国产一区二区三区 | 亚洲一区二区在线视频 | 91在线区|