Java 菜鳥教程

Java 流程控制

Java 數(shù)組

Java 面向?qū)ο?I)

Java 面向?qū)ο?II)

Java 面向?qū)ο?III)

Java 異常處理

Java 列表(List)

Java Queue(隊(duì)列)

Java Map集合

Java Set集合

Java 輸入輸出(I/O)

Java Reader/Writer

Java 其他主題

Java 異常處理

在本教程中,您將借助示例學(xué)習(xí)如何用Java處理異常。為了處理異常,我們將使用try ... catch ... finally塊。

在上一教程中,我們了解了異常。異常是程序執(zhí)行期間發(fā)生的意外事件。

捕捉和處理異常

在Java中,我們使用異常處理程序組件try,catch和finally塊來處理異常。

為了捕獲和處理異常,我們將try...catch...finally代碼塊放置在可能產(chǎn)生異常的代碼周圍。finally塊是可選的。

try...catch...finally的語法為:

try {
  // 代碼
} catch (ExceptionType e) { 
  // 捕獲塊
} finally {
  //finally塊
}

Java try ... catch塊

可能會(huì)生成異常的代碼放在try塊中。

每個(gè)try塊后面應(yīng)緊跟著catch 或 finally塊。發(fā)生異常時(shí),它會(huì)被catch緊隨其后的塊捕獲。

 catch塊不能單獨(dú)使用,必須緊隨try塊。

示例1:try ... catch塊

class Main {
  public static void main(String[] args) {

    try {
      int divideByZero = 5 / 0;
      System.out.println("try塊中的其余代碼");
    } catch (ArithmeticException e) {
      System.out.println("ArithmeticException => " + e.getMessage());
    }

  }
}

輸出結(jié)果

ArithmeticException => / by zero

在這個(gè)實(shí)例中

  • 我們?cè)趖ry塊中將數(shù)字除以0。這產(chǎn)生一個(gè)ArithmeticException。

  • 發(fā)生異常時(shí),程序?qū)⑻^try塊中的其余代碼。

  • 在這里,我們創(chuàng)建了一個(gè)catch塊來處理ArithmeticException。因此,將catch執(zhí)行塊內(nèi)的語句。

如果該try塊中的所有語句均未生成異常,則跳過catch代碼塊。

多個(gè)捕獲塊

對(duì)于每個(gè)try塊,可以有零個(gè)或多個(gè)catch塊。

每個(gè)catch塊的參數(shù)類型指示可以處理的異常類型。多個(gè)catch塊使我們能夠以不同方式處理每個(gè)異常。

示例2:多個(gè)捕獲塊

class ListOfNumbers {
  public int[] arrayOfNumbers = new int[10];

  public void writeList() {

    try {
      arrayOfNumbers[10] = 11;
    } catch (NumberFormatException e1) {
      System.out.println("NumberFormatException => " + e1.getMessage());
    } catch (IndexOutOfBoundsException e2) {
      System.out.println("IndexOutOfBoundsException => " + e2.getMessage());
    }

  }
}

class Main {
  public static void main(String[] args) {
    ListOfNumbers list = new ListOfNumbers();
    list.writeList();
  }
}

輸出結(jié)果

IndexOutOfBoundsException => Index 10 out of bounds for length 10

在此示例中,我們聲明了一個(gè)大小為10 的整數(shù)數(shù)組arrayOfNumbers。

我們知道數(shù)組索引總是從0開始。因此,當(dāng)我們嘗試為索引10分配一個(gè)值時(shí),就會(huì)發(fā)生IndexOutOfBoundsException,因?yàn)閿?shù)組arrayOfNumbers的邊界是0到9。

當(dāng)try塊中發(fā)生異常時(shí),

  • 異常被拋出給第一個(gè)catch塊。第一個(gè)catch塊不處理IndexOutOfBoundsException異常,因此它被傳遞給下一個(gè)catch塊。

  • 上面示例中的第二個(gè)catch塊是適當(dāng)?shù)漠惓L幚沓绦?,因?yàn)樗幚鞩ndexOutOfBoundsException。 因此,它被執(zhí)行。

Java Finally塊

對(duì)于每個(gè)try塊,只能有一個(gè)finally塊。

finally塊是可選的。但是,如果已定義,它將始終執(zhí)行(即使不會(huì)發(fā)生異常)。

如果發(fā)生異常,則在try...catch塊之后執(zhí)行。如果沒有異常發(fā)生,則在try塊之后執(zhí)行。

finally塊的基本語法為:

try {
  //code
} catch (ExceptionType1 e1) { 
  // catch 塊
} catch (ExceptionType1 e2) {
 // catch 塊
} finally {
  //finally塊一直執(zhí)行
}

示例3:finally塊示例

class Main {
  public static void main(String[] args) {
    try {
      int divideByZero = 5 / 0;
    } catch (ArithmeticException e) {
      System.out.println("ArithmeticException => " + e.getMessage());
    } finally {
      System.out.println("Finally塊總是執(zhí)行");
    }
  }
}

輸出結(jié)果

ArithmeticException => / by zero
Finally塊總是執(zhí)行

在此示例中,我們將數(shù)字除以0。這引發(fā)了一個(gè)ArithmeticException被catch塊捕獲,finally塊始終執(zhí)行。

使用finally塊被認(rèn)為是一種很好的做法。這是因?yàn)樗酥匾那謇泶a,例如

  • 可能被return、continue或break語句意外跳過的代碼

  • 關(guān)閉文件或連接

我們已經(jīng)提到,finally總是執(zhí)行,通常是這樣的。但是,在某些情況下,finally塊不執(zhí)行:

  • 使用 System.exit()方法

  • finally塊中發(fā)生異常

  • 線程被終止

示例4:try, catch 和finally示例

讓我們舉一個(gè)實(shí)例,我們嘗試使用FileWriter創(chuàng)建一個(gè)新文件,并使用PrintWriter寫入數(shù)據(jù)。

import java.io.*;

class ListOfNumbers {
  private int[] list = new int[10];

  public ListOfNumbers() {
    //在列表數(shù)組中存儲(chǔ)整數(shù)值
    for (int i = 0; i < 10; i++) {
      list[i] = i;
    } 	
  }

}

  public void writeList() {
    PrintWriter out = null;

    try {
      System.out.println("進(jìn)入try語句");

      //創(chuàng)建一個(gè)新文件OutputFile.txt
      out = new PrintWriter(new FileWriter("OutputFile.txt"));

      //將值從列表數(shù)組寫入新創(chuàng)建的文件
      for (int i = 0; i < 10; i++) {
        out.println("Value at: " + i + " = " + list[i]);
      }
    } catch (IndexOutOfBoundsException e1) {
      System.out.println("IndexOutOfBoundsException => " + e1.getMessage());
    } catch (IOException e2) {
      System.out.println("IOException => " + e2.getMessage());
    } finally {
      //檢查PrintWriter是否被打開
      if (out != null) {
        System.out.println("關(guān)閉PrintWriter");
        out.close();
      } else {
        System.out.println("PrintWriter無法打開");
      }
    }

  }
}

class Main {
  public static void main(String[] args) {
    ListOfNumbers list = new ListOfNumbers();
    list.writeList();
  }
}

當(dāng)您運(yùn)行此程序時(shí),可能會(huì)發(fā)生兩種可能性:

  1. try塊中發(fā)生異常

  2. try塊正常執(zhí)行

創(chuàng)建新的FileWriter時(shí)可能會(huì)發(fā)生異常。 如果無法創(chuàng)建或?qū)懭胫付ǖ奈募?,則拋出IOException。

當(dāng)發(fā)生異常時(shí),我們將獲得以下輸出。

進(jìn)入try語句
IOException => OutputFile.txt
PrintWriter無法打開

當(dāng)未發(fā)生異常且該try塊正常執(zhí)行時(shí),我們將獲得以下輸出。

進(jìn)入try語句
關(guān)閉PrintWriter

將創(chuàng)建一個(gè)OutputFile.txt,并包含以下內(nèi)容

Value at: 0 = 0
Value at: 1 = 1
Value at: 2 = 2
Value at: 3 = 3
Value at: 4 = 4
Value at: 5 = 5
Value at: 6 = 6
Value at: 7 = 7
Value at: 8 = 8
Value at: 9 = 9

try ... catch...finally 詳細(xì)流程

讓我們嘗試在上述示例的幫助下詳細(xì)了解異常處理的流程。

try ... catch...finally 詳細(xì)流程

上圖描述了在創(chuàng)建新FileWriter時(shí)發(fā)生異常時(shí)的程序執(zhí)行流程。

  • 為了找到發(fā)生異常的方法,主方法調(diào)用writeList()方法,該方法隨后調(diào)用FileWriter()方法來創(chuàng)建一個(gè)新的OutputFile.txt文件。

  • 發(fā)生異常時(shí),運(yùn)行時(shí)系統(tǒng)將跳過try塊中的其余代碼。

  • 它開始以相反的順序搜索調(diào)用堆棧,以找到合適的異常處理程序。

  • 這里,F(xiàn)ileWriter沒有異常處理程序,因此運(yùn)行時(shí)系統(tǒng)檢查調(diào)用堆棧中的下一個(gè)方法,即writeList。

  • writeList方法有兩個(gè)異常處理程序:一個(gè)處理IndexOutOfBoundsException,另一個(gè)處理IOException。

  • 然后,系統(tǒng)依次處理這些處理程序。

  • 此示例中的第一個(gè)處理程序處理IndexOutOfBoundsException。 這與try塊引發(fā)的IOException不匹配。

  • 因此,檢查下一個(gè)處理程序是哪個(gè)IOException處理程序。如與引發(fā)的異常類型匹配,因此將執(zhí)行對(duì)應(yīng)catch塊中的代碼。

  • 執(zhí)行異常處理程序后,將執(zhí)行finally塊。

  • 在此場(chǎng)景中,由于FileWriter中發(fā)生了異常,所以PrintWriter對(duì)象out從未打開,因此不需要關(guān)閉。

現(xiàn)在,讓我們假設(shè)在運(yùn)行該程序時(shí)沒有發(fā)生異常,并且try塊正常執(zhí)行。 在這種情況下,將創(chuàng)建并寫入一個(gè)OutputFile.txt。

眾所周知,finally塊的執(zhí)行與異常處理無關(guān)。由于沒有異常發(fā)生,因此PrintWriter打開了并且需要關(guān)閉。這是通過finally塊中的out.close()語句完成的。

捕獲多個(gè)異常

從Java SE 7和更高版本開始,我們現(xiàn)在可以用一個(gè)catch塊捕獲不止一種類型的異常。

這樣可以減少代碼重復(fù)并提高代碼的簡(jiǎn)單性和效率。

可以由catch塊處理的每種異常類型都使用豎線(|)分隔。

其語法為:

try {
  // code
} catch (ExceptionType1 | Exceptiontype2 ex) { 
  // catch block
}

要了解更多信息,請(qǐng)?jiān)L問Java捕獲多個(gè)異常。

try-with-resources語句

try-with-resources語句是一種try語句,具有一個(gè)或多個(gè)資源聲明。

其語法為:

try (resource declaration) {
  // use of the resource
} catch (ExceptionType e1) {
  // catch block
}

資源是在程序結(jié)束時(shí)要關(guān)閉的對(duì)象。必須在try語句中聲明和初始化它。

讓我們舉個(gè)實(shí)例。

try (PrintWriter out = new PrintWriter(new FileWriter("OutputFile.txt")) {
  // use of the resource
}

try-with-resources語句也稱為自動(dòng)資源管理。該語句在語句末尾自動(dòng)關(guān)閉所有資源。

要了解更多信息,請(qǐng)?jiān)L問Java try-with-resources語句。

丰满人妻一级特黄a大片,午夜无码免费福利一级,欧美亚洲精品在线,国产婷婷成人久久Av免费高清