欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一篇文章解決Java異常處理

 更新時(shí)間:2020年09月03日 10:03:57   作者:今天的喝了碗雞湯  
這篇文章主要給大家介紹了關(guān)于如何通過一篇文章解決Java異常處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

與異常相關(guān)的內(nèi)容其實(shí)很早就想寫了,但由于各種原因(懶)拖到了現(xiàn)在。在大二開學(xué)前夜(今天是8.31)完成這篇博客,也算完成了暑期生活的一個(gè)小心愿。

以下內(nèi)容大多總結(jié)自《Java核心技術(shù) 卷Ⅰ》,同時(shí)也加上了一些華東師范大學(xué)陳良育老師在《Java核心技術(shù)》Mooc中所講的內(nèi)容。

一、引例

假定你希望完成一個(gè)read方法,它的作用是讀取一個(gè)文件中的內(nèi)容并進(jìn)行相關(guān)處理,如果你從未學(xué)過處理異常的方法,你可能會(huì)這樣寫:

public void read(String filename)
{
 var in = new FileInputStream(filename);
 int b;
 while((b = in.read()) != -1)
 {
  ... 
 }
}

問題在于,F(xiàn)ileInputStream的構(gòu)造器要求傳入的filename是已經(jīng)存在的一個(gè)文件的名稱,如果文件名不存在,那么程序?qū)惓=K止,可能導(dǎo)致用戶在運(yùn)行程序期間所做的工作全部丟失,這顯然不是我們希望看到的。
正確的做法之一是增加一個(gè)異常處理機(jī)制,將控制權(quán)從產(chǎn)生錯(cuò)誤的地方轉(zhuǎn)移到能夠處理這種錯(cuò)誤的處理器中。這樣就可以盡可能的減少損失。

public void read(String filename)
{
  try
  {
   var in = new FileInputStream(filename);
   int b;
   while((b = in.read()) != -1)
   {
     ...
   }
  }
  catch(IOException exception)
  {
   ...//處理錯(cuò)誤
  }
}
//里面可能有些代碼你暫且還不明白,不過沒關(guān)系,之后會(huì)認(rèn)真講解。

二、異常的分類與類型

在Java中,每種異常都是一個(gè)類(如上例中的IOException),每個(gè)異常對象都是一個(gè)實(shí)例。

  1. 所有的異常都是由Throwable類繼承而來。
  2. Throwable類的下一層有兩個(gè)分支:Error類和Exception類
  3. Exception類又分解為RuntimeException(編程錯(cuò)誤導(dǎo)致的異常)與IOException(其他異常)

Error類:描述Java運(yùn)行時(shí)系統(tǒng)內(nèi)部錯(cuò)誤和資源耗盡錯(cuò)誤。 RuntimeException類:編程錯(cuò)誤。例如數(shù)組越界訪問、錯(cuò)誤的強(qiáng)制類型轉(zhuǎn)換、訪問null指針等。
IOException類:其他異常。例如打開不存在的文件等等。

對于Error異常,我們無能為力;而對于RuntimeException異常,我們要做的是預(yù)防而非處理,譬如在程序中寫好檢測數(shù)組下標(biāo)是否越界的代碼、在使用變量前檢測它是否為null;我們重點(diǎn)處理的對象是IOException異常。

鑒于上述特性,Error與RuntimeException異常在Java語言規(guī)范中被稱為非檢查型異常;IOException稱為檢查型異常。編譯器只會(huì)幫助你檢查是否為所有的檢查型異常提供了異常處理器。

三、處理檢查型異常之方法一:聲明與拋出

如果你知道一個(gè)方法會(huì)產(chǎn)生某種(或多種)檢查型異常,但又不想處理這個(gè)異常(或無法處理),可以選擇僅聲明該類異常,將異常的處理交由調(diào)用這個(gè)方法的人。

具體的操作方式為:在方法名稱后面加上 throws + 異常類型,程序中如果真的遇到了這種異常,則 throw + 異常類的對象拋出異常。

String readData(Scanner in) throws EOFException
{
  ...
  while(...)
  {
   if(!in.hasNext())
   {
     if(n < len)//遇見EOFException異常
     {
      throw new EOFException();//拋出異常
     }
     ...
   }
   return s;
  }
}

聲明異常時(shí)請注意:

  • 如果一個(gè)方法可能拋出多個(gè)檢查型異常,則必須列出所有的檢查型的異常類。(否則編譯器會(huì)發(fā)出一個(gè)錯(cuò)誤消息)
public void read(String filename) throws FileNotFoundException, EOFException
  • 如果子類覆蓋了父類中的一個(gè)方法,則子類中該方法對異常的聲明范圍不能超過父類(即子類中覆蓋的方法要么拋出更具體的異常,要么不拋出異常)。
  • 如果一個(gè)方法聲明它會(huì)拋出一個(gè)異常,那么這個(gè)方法拋出的異??赡軐儆谶@個(gè)類,也可能屬于這個(gè)類的子類。

拋出異常時(shí)請注意:

  • 如果一個(gè)方法調(diào)用了拋出檢查型異常的方法,這個(gè)方法要么處理這個(gè)異常(怎么處理標(biāo)題五會(huì)詳細(xì)介紹),要么繼續(xù)傳遞這個(gè)異常(即繼續(xù)throws)。
  • 如果一個(gè)方法是覆蓋了超類中的方法,并且在超類中這個(gè)方法沒有拋出異常,那么你別無選擇,必須處理所有可能發(fā)生的檢查型異常(因?yàn)樽宇愔械母采w方法拋出范圍不得超過父類)。

四、定義自己的異常類

標(biāo)題三中的處理方法雖然簡便,但有一個(gè)很大的缺點(diǎn):你必須找到一個(gè)合適的可能觸發(fā)的異常類別,才能將其拋出。于是我們想,可不可以自己定義一個(gè)異常類別,這樣即使我們找不到合適的異常類,也可以將其拋出?

通常讓自定義的類繼承于Exception類或者IOException類,并且按照習(xí)慣,任何異常類都至少需要包含兩個(gè)構(gòu)造器,一個(gè)是默認(rèn)構(gòu)造器,另一個(gè)是包含有詳細(xì)描述信息的構(gòu)造器(方便調(diào)試)。
舉例:

class FileFormatException extends IOException//自定義異常類
{
  public FileFormatException(){}
  public FileFormarException(String gripe)
  {
   super(gripe);
  }
}

String readData(BufferedReader in) throw FileFormatException//聲明自定義的異常
{
  ...
  while(...)
  {
   if(ch == -1) 
   {
     if(n < len) throw new FileFormatException();//拋出自定義的異常
   }
  }
}

五、處理檢查型異常之方法二:try-catch-finally捕獲異常

現(xiàn)在讓我們回到引例上來:

public void read(String filename)
{
  try
  {
   var in = new FileInputStream(filename);
   int b;
   while((b = in.read()) != -1)
   {
     ...
   }
  }
  catch(IOException exception)
  {
   ...
  }
}

小知識(shí):“如果發(fā)生了某個(gè)異常,但沒有被捕獲,程序就會(huì)終止,并在控制臺(tái)上打印一個(gè)消息,其中包括這個(gè)異常的類型和一個(gè)堆棧軌跡?!?/p>

引例中完成的是一個(gè)最簡單的 try-catch 語句,現(xiàn)在我們來分析一下不同情況下程序相應(yīng)的執(zhí)行情況:

  • 如果 try 中出現(xiàn)了一個(gè)異常,且該異常被成功捕獲(在上例中即異常類型剛好為catch中的IOException類型)。則程序會(huì)跳過 try 中其余代碼,接著執(zhí)行 catch 子句中的代碼。
  • 如果 try 中出現(xiàn)了一個(gè)異常,且該異常未被成功捕獲(即異常類型與catch中的異常類型不符)。則程序會(huì)立即退出。
  • 如果 try 中未出現(xiàn)任何異常,將不會(huì)執(zhí)行 catch 中的語句。

多 catch 捕獲多個(gè)異常:

在一個(gè)try語句塊中可以捕獲多個(gè)異常類型,并對每個(gè)異常類型使用一個(gè)單獨(dú)的 catch 子句。并且,自 Java 7之后,允許一個(gè) catch 子句捕獲多個(gè)異常類型。

try
{
 ...
}
catch(FileNotFoundException | UnknownHostException e)//一個(gè)catch捕獲多個(gè)異常
{
 ...
}
catch(IOException e)//一個(gè) try 語句塊中多個(gè) catch 語句
{
 ...
}

注意:

  • 用一個(gè)catch捕獲多個(gè)異常時(shí),異常變量隱含為final變量,因此不允許為 e 賦于不同的值。
  • 多個(gè)catch子塊存在時(shí),由于程序是由上往下依次捕捉,不允許將父類異常寫在子類的上方。
  • catch語塊中允許再次拋出異常(throw語句)

try-catch-finally語句:

假定這樣一種情況,一個(gè)程序在 try 中使用了一些本地資源,而且這些資源必須在程序退出時(shí)進(jìn)行清理。如果只用try-catch方法,那么每個(gè)catch語句中都要重復(fù)書寫清理資源的代碼,顯得非常笨重且繁瑣?,F(xiàn)在,我們可以用finally語句來解決這個(gè)問題,它的特定是:不管異常有無被捕獲,finally語句中的代碼都會(huì)執(zhí)行。功能是:確保資源被清理。

示例:在finally語句中關(guān)閉輸出流

var in = new FileInputStream(...)
try
{
 //1
 可能發(fā)生異常的語句
 //2
}
catch (IOException e)
{
 //3
 展示錯(cuò)誤信息
 //4
}
finally
{
 //5
 in.close();//關(guān)閉輸出流
}
//6

現(xiàn)在我們來分析一下不同情況下程序相應(yīng)的執(zhí)行情況:

  • try 中代碼未拋出異常。執(zhí)行1256。
  • try 中代碼拋出異常并且被捕獲且 catch沒有拋出異常。執(zhí)行13456。
  • try 中代碼拋出異常并且被捕獲但 catch拋出異常。執(zhí)行135。
  • try 中代碼拋出異常但未被捕獲。執(zhí)行15。

總結(jié)一下,

執(zhí)行6的條件是,走完了整個(gè) try / catch塊。

執(zhí)行5的條件是,任何條件都會(huì)執(zhí)行。

注意:

  • 允許一個(gè)catch塊都沒有。
  • 允許try / catch / finally子塊中嵌套一個(gè)try-catch-finally塊。
  • 千萬不要在finally子塊中使用改變控制流的語句!(return,throw,break,continue)。因?yàn)閒inally的執(zhí)行在try之后,整個(gè)方法返回之前,因此在finally子塊中改變控制流將會(huì)覆蓋 try 中的結(jié)果。(這個(gè)結(jié)果可以是一個(gè)return值,也可以是一個(gè)異常)。

六、額外補(bǔ)充之try-with-Resources語句

Java中存在一個(gè)AutoCloseable接口

public interface AutoCloseable
{
  void close() throws Exception;
}

假定資源屬于一個(gè)實(shí)現(xiàn)了AutoCloseable接口的類,那么處理異常時(shí)可以不需要finally子塊。因?yàn)樵撡Y源無論是正常退出或產(chǎn)生異常,都會(huì)自動(dòng)調(diào)用close方法,代替了finally子塊。

帶資源的try語句通用格式:

try(Resources res = ...)
{
  work with Resources;
}

舉例如下:

try(var in = new Scanner(...))
{
  while(in.hashNext()) System.out.println(in.next());
}//無論 try塊怎么樣退出,都會(huì)執(zhí)行 in.close();

這種方式使得代碼看起來更加簡潔。

請注意:

  • try-with-Resources語句允許有catch / finally子句。它們會(huì)在資源關(guān)閉后再執(zhí)行。

最后的最后,希望提醒大家,捕獲異常雖然方便,但會(huì)極大的延長程序運(yùn)行的時(shí)間,因此,只在必要條件下使用異常。

總結(jié)

到此這篇關(guān)于一篇文章解決Java異常處理的文章就介紹到這了,更多相關(guān)Java異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java8中新的Date和Time詳解

    java8中新的Date和Time詳解

    這篇文章主要是java8中新的Date和Time,探討新Date類和Time類背后的設(shè)計(jì)原則,有所需要的小伙伴希望能幫助到你
    2016-07-07
  • Java常用數(shù)字工具類 數(shù)字轉(zhuǎn)漢字(1)

    Java常用數(shù)字工具類 數(shù)字轉(zhuǎn)漢字(1)

    這篇文章主要為大家詳細(xì)介紹了Java常用數(shù)字工具類,數(shù)字轉(zhuǎn)漢字,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 深入理解JVM垃圾回收算法

    深入理解JVM垃圾回收算法

    我們都知道java語言與C語言最大的區(qū)別就是內(nèi)存自動(dòng)回收,那么JVM是怎么控制內(nèi)存回收的,這篇文章將介紹JVM垃圾回收的幾種算法,從而了解內(nèi)存回收的基本原理
    2021-06-06
  • JAVA十大排序算法之堆排序詳解

    JAVA十大排序算法之堆排序詳解

    這篇文章主要介紹了java中的冒泡排序,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考
    2021-08-08
  • Springboot整合Jedis實(shí)現(xiàn)單機(jī)版或哨兵版可切換配置方法

    Springboot整合Jedis實(shí)現(xiàn)單機(jī)版或哨兵版可切換配置方法

    這篇文章主要介紹了Springboot整合Jedis實(shí)現(xiàn)單機(jī)版或哨兵版可切換配置方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-11-11
  • Mybatis一對多關(guān)聯(lián)關(guān)系映射實(shí)現(xiàn)過程解析

    Mybatis一對多關(guān)聯(lián)關(guān)系映射實(shí)現(xiàn)過程解析

    這篇文章主要介紹了Mybatis一對多關(guān)聯(lián)關(guān)系映射實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 詳解Java sort()數(shù)組排序(升序和降序)

    詳解Java sort()數(shù)組排序(升序和降序)

    這篇文章主要介紹了詳解Java sort()數(shù)組排序(升序和降序),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • spring?boot項(xiàng)目中如何使用nacos作為配置中心

    spring?boot項(xiàng)目中如何使用nacos作為配置中心

    這篇文章主要介紹了spring?boot項(xiàng)目中如何使用nacos作為配置中心問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • java 中設(shè)計(jì)模式(值對象)的實(shí)例詳解

    java 中設(shè)計(jì)模式(值對象)的實(shí)例詳解

    這篇文章主要介紹了java 中設(shè)計(jì)模式(值對象)的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Spring?Boot自動(dòng)配置源碼實(shí)例解析

    Spring?Boot自動(dòng)配置源碼實(shí)例解析

    Spring Boot作為Java領(lǐng)域最為流行的快速開發(fā)框架之一,其核心特性之一就是其強(qiáng)大的自動(dòng)配置機(jī)制,下面這篇文章主要給大家介紹了關(guān)于Spring?Boot自動(dòng)配置源碼的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08

最新評(píng)論