亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Java? 教程(捕獲和處理異常)

Yujiaao / 736人閱讀

捕獲和處理異常

本節(jié)描述如何使用三個異常處理程序組件 — trycatchfinally塊 — 來編寫異常處理程序,然后,解釋了Java SE 7中引入的try-with-resources語句,try-with-resources語句特別適用于使用Closeable資源的情況,例如流。

本節(jié)的最后一部分將介紹一個示例,并分析各種場景中發(fā)生的情況。

以下示例定義并實現(xiàn)名為ListOfNumbers的類,構(gòu)造時,ListOfNumbers創(chuàng)建一個ArrayList,其中包含10個具有順序值0到9的整數(shù)元素,ListOfNumbers類還定義了一個名為writeList的方法,該方法將數(shù)字列表寫入名為OutFile.txt的文本文件中,此示例使用java.io中定義的輸出類,這些類在基礎(chǔ)I/O中介紹。

// Note: This class will not compile yet.
import java.io.*;
import java.util.List;
import java.util.ArrayList;

public class ListOfNumbers {

    private List list;
    private static final int SIZE = 10;

    public ListOfNumbers () {
        list = new ArrayList(SIZE);
        for (int i = 0; i < SIZE; i++) {
            list.add(new Integer(i));
        }
    }

    public void writeList() {
    // The FileWriter constructor throws IOException, which must be caught.
        PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));

        for (int i = 0; i < SIZE; i++) {
            // The get(int) method throws IndexOutOfBoundsException, which must be caught.
            out.println("Value at: " + i + " = " + list.get(i));
        }
        out.close();
    }
}

FileWriter構(gòu)造函數(shù)初始化文件上的輸出流,如果無法打開該文件,則構(gòu)造函數(shù)將拋出IOException。對ArrayList類的get方法的調(diào)用,如果其參數(shù)的值太?。ㄐ∮?)或太大(大于ArrayList當(dāng)前包含的元素數(shù)),則拋出IndexOutOfBoundsException。

如果你嘗試編譯ListOfNumbers類,編譯器將輸出有關(guān)FileWriter構(gòu)造函數(shù)拋出的異常的錯誤消息,但是,它不會顯示有關(guān)get拋出的異常的錯誤消息,原因是構(gòu)造函數(shù)拋出的異常IOException是一個經(jīng)過檢查的異常,而get方法拋出的異常(IndexOutOfBoundsException)是一個未經(jīng)檢查的異常。

現(xiàn)在你已熟悉ListOfNumbers類以及可以在其中拋出異常的位置,你已準(zhǔn)備好編寫異常處理程序來捕獲和處理這些異常。

try塊

構(gòu)造異常處理程序的第一步是使用try塊將可能引發(fā)異常的代碼括起來,通常,try塊如下所示:

try {
    code
}
catch and finally blocks . . .

標(biāo)記為code的示例段中包含一個或多個可能引發(fā)異常的合法代碼行(catchfinally塊將在接下來的兩個小節(jié)中解釋)。

要從ListOfNumbers類構(gòu)造writeList方法的異常處理程序,請將writeList方法的異常拋出語句包含在try塊中,有不止一種方法可以做到這一點,你可以將可能引發(fā)異常的每行代碼放在其自己的try塊中,并為每個代碼提供多帶帶的異常處理程序?;蛘?,你可以將所有writeList代碼放在一個try塊中,并將多個處理程序與它相關(guān)聯(lián),以下列表對整個方法使用一個try塊,因為所討論的代碼非常短。

private List list;
private static final int SIZE = 10;

public void writeList() {
    PrintWriter out = null;
    try {
        System.out.println("Entered try statement");
        out = new PrintWriter(new FileWriter("OutFile.txt"));
        for (int i = 0; i < SIZE; i++) {
            out.println("Value at: " + i + " = " + list.get(i));
        }
    }
    catch and finally blocks  . . .
}

如果try塊中發(fā)生異常,則該異常由與之關(guān)聯(lián)的異常處理程序處理,要將異常處理程序與try塊關(guān)聯(lián),必須在其后面放置一個catch塊。

catch塊

通過在try塊之后直接提供一個或多個catch塊,可以將異常處理程序與try塊關(guān)聯(lián),try塊的末尾和第一個catch塊的開頭之間不能有代碼。

try {

} catch (ExceptionType name) {

} catch (ExceptionType name) {

}

每個catch塊都是一個異常處理程序,它處理由其參數(shù)表示的異常類型,參數(shù)類型ExceptionType聲明了處理程序可以處理的異常類型,并且必須是從Throwable類繼承的類的名稱,處理程序可以使用name引用異常。

catch塊包含在調(diào)用異常處理程序時執(zhí)行的代碼,當(dāng)處理程序是調(diào)用堆棧中的第一個ExceptionType與拋出的異常類型匹配時,運行時系統(tǒng)調(diào)用此異常處理程序,如果拋出的對象可以合法地分配給異常處理程序的參數(shù),則系統(tǒng)認(rèn)為它是匹配的。

以下是writeList方法的兩個異常處理程序:

try {

} catch (IndexOutOfBoundsException e) {
    System.err.println("IndexOutOfBoundsException: " + e.getMessage());
} catch (IOException e) {
    System.err.println("Caught IOException: " + e.getMessage());
}

異常處理程序不僅可以打印錯誤消息或停止程序,它們可以執(zhí)行錯誤恢復(fù)、提示用戶做出決定,或使用鏈?zhǔn)疆惓㈠e誤傳播到更高級別的處理程序,如“鏈?zhǔn)疆惓!辈糠炙觥?/p> 使用一個異常處理程序捕獲多種類型的異常

在Java SE 7及更高版本中,單個catch塊可以處理多種類型的異常,此功能可以減少代碼重復(fù)并減少捕獲過于寬泛的異常的誘惑。

catch子句中,指定塊可以處理的異常類型,并使用豎線(|)分隔每個異常類型:

catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}
注意:如果catch塊處理多個異常類型,則catch參數(shù)隱式為final,在此示例中,catch參數(shù)exfinal,因此你無法在catch塊中為其分配任何值。
finally塊

當(dāng)try塊退出時,finally塊總是執(zhí)行,這確保即使發(fā)生意外異常也會執(zhí)行finally塊,但finally不僅僅是異常處理有用 — 它允許程序員避免因returncontinuebreak而意外繞過清理代碼,將清理代碼放在finally塊中始終是一種很好的做法,即使沒有預(yù)期的異常情況也是如此。

注意:如果在執(zhí)行trycatch代碼時JVM退出,則finally塊可能無法執(zhí)行,同樣,如果執(zhí)行trycatch代碼的線程被中斷或終止,則即使應(yīng)用程序作為一個整體繼續(xù),finally塊也可能無法執(zhí)行。

你在此處使用的writeList方法的try塊打開了PrintWriter,程序應(yīng)該在退出writeList方法之前關(guān)閉該流,這帶來了一個有點復(fù)雜的問題,因為writeListtry塊可以以三種方式之一退出。

new FileWriter語句失敗并拋出IOException。

list.get(i)語句失敗并拋出IndexOutOfBoundsException。

一切都成功,try塊正常退出。

無論try塊中發(fā)生了什么,運行時系統(tǒng)總是執(zhí)行finally塊中的語句,所以這是進(jìn)行清理的最佳地點。

下面的writeList方法的finally塊清理然后關(guān)閉PrintWriter

finally {
    if (out != null) { 
        System.out.println("Closing PrintWriter");
        out.close(); 
    } else { 
        System.out.println("PrintWriter not open");
    } 
}
重要提示:finally塊是防止資源泄漏的關(guān)鍵工具,關(guān)閉文件或以其他方式恢復(fù)資源時,將代碼放在finally塊中以確保始終恢復(fù)資源。

請考慮在這些情況下使用try-with-resources語句,這會在不再需要時自動釋放系統(tǒng)資源,try-with-resources語句部分提供了更多信息。

try-with-resources語句

try-with-resources語句是一個聲明一個或多個資源的try語句,資源是在程序完成后必須關(guān)閉的對象,try-with-resources語句確保在語句結(jié)束時關(guān)閉每個資源,實現(xiàn)java.lang.AutoCloseable的任何對象(包括實現(xiàn)java.io.Closeable的所有對象)都可以用作資源。

以下示例從文件中讀取第一行,它使用BufferedReader實例從文件中讀取數(shù)據(jù),BufferedReader是一個在程序完成后必須關(guān)閉的資源:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

在此示例中,try-with-resources語句中聲明的資源是BufferedReader,聲明語句出現(xiàn)在try關(guān)鍵字后面的括號內(nèi),Java SE 7及更高版本中的BufferedReader類實現(xiàn)了java.lang.AutoCloseable接口,因為BufferedReader實例是在try-with-resource語句中聲明的,所以無論try語句是正常完成還是突然完成(由于BufferedReader.readLine方法拋出IOException),它都將被關(guān)閉。

在Java SE 7之前,你可以使用finally塊來確保關(guān)閉資源,無論try語句是正常還是突然完成,以下示例使用finally塊而不是try-with-resources語句:

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

但是,在此示例中,如果方法readLineclose都拋出異常,則方法readFirstLineFromFileWithFinallyBlock拋出finally塊拋出的異常,從try塊拋出的異常被抑制。相反,在示例readFirstLineFromFile中,如果從try塊和try-with-resources語句拋出異常,則readFirstLineFromFile方法拋出try塊拋出的異常,從try-with-resources塊拋出的異常被抑制,在Java SE 7及更高版本中,你可以檢索已抑制的異常,有關(guān)詳細(xì)信息,請參閱“抑制的異?!辈糠?。

你可以在try-with-resources語句中聲明一個或多個資源,以下示例檢索zip文件zipFileName中打包的文件的名稱,并創(chuàng)建包含這些文件名稱的文本文件:

public static void writeToFileZipFileContents(String zipFileName,
                                           String outputFileName)
                                           throws java.io.IOException {

    java.nio.charset.Charset charset =
         java.nio.charset.StandardCharsets.US_ASCII;
    java.nio.file.Path outputFilePath =
         java.nio.file.Paths.get(outputFileName);

    // Open zip file and create output file with 
    // try-with-resources statement

    try (
        java.util.zip.ZipFile zf =
             new java.util.zip.ZipFile(zipFileName);
        java.io.BufferedWriter writer = 
            java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {
        // Enumerate each entry
        for (java.util.Enumeration entries =
                                zf.entries(); entries.hasMoreElements();) {
            // Get the entry name and write it to the output file
            String newLine = System.getProperty("line.separator");
            String zipEntryName =
                 ((java.util.zip.ZipEntry)entries.nextElement()).getName() +
                 newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
        }
    }
}

在此示例中,try-with-resources語句包含兩個以分號分隔的聲明:ZipFileBufferedWriter,當(dāng)直接跟隨它的代碼塊正常或由于異常而終止時,將按此順序自動調(diào)用BufferedWriterZipFile對象的close方法,請注意,資源的close方法按其創(chuàng)建的相反順序調(diào)用。

以下示例使用try-with-resources語句自動關(guān)閉java.sql.Statement對象:

public static void viewTable(Connection con) throws SQLException {

    String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES";

    try (Statement stmt = con.createStatement()) {
        ResultSet rs = stmt.executeQuery(query);

        while (rs.next()) {
            String coffeeName = rs.getString("COF_NAME");
            int supplierID = rs.getInt("SUP_ID");
            float price = rs.getFloat("PRICE");
            int sales = rs.getInt("SALES");
            int total = rs.getInt("TOTAL");

            System.out.println(coffeeName + ", " + supplierID + ", " + 
                               price + ", " + sales + ", " + total);
        }
    } catch (SQLException e) {
        JDBCTutorialUtilities.printSQLException(e);
    }
}

此示例中使用的資源java.sql.Statement是JDBC 4.1及更高版本API的一部分。

注意:try-with-resources語句可以像普通的try語句一樣有catchfinally塊,在try-with-resources語句中,在聲明的資源關(guān)閉后運行任何catchfinally塊。
抑制異常

可以從與try-with-resources語句關(guān)聯(lián)的代碼塊中拋出異常,在示例writeToFileZipFileContents中,可以從try塊拋出異常,當(dāng)try-with-resources語句嘗試關(guān)閉ZipFileBufferedWriter對象時,最多可以拋出兩個異常。如果從try塊拋出異常,并且從try-with-resources語句中拋出一個或多個異常,則會抑制從try-with-resources語句拋出的那些異常,并且塊拋出的異常是writeToFileZipFileContents方法拋出的異常,你可以通過從try塊拋出的異常中調(diào)用Throwable.getSuppressed方法來檢索這些抑制的異常。

實現(xiàn)AutoCloseable或Closeable接口的類

請參閱AutoCloseable和Closeable接口的Javadoc,以獲取實現(xiàn)這些接口之一的類列表,Closeable接口擴(kuò)展了AutoCloseable接口。Closeable接口的close方法拋出IOException類型的異常,而AutoCloseable接口的close方法拋出異常類型Exception,因此,AutoCloseable接口的子類可以覆蓋close方法的這種行為,以拋出專門的異常,例如IOException,或者根本沒有異常。

把它們放在一起

前面的部分描述了如何為ListOfNumbers類中的writeList方法構(gòu)造trycatchfinally代碼塊,現(xiàn)在,讓我們來看看代碼并調(diào)查會發(fā)生什么。

將所有組件放在一起時,writeList方法如下所示。

public void writeList() {
    PrintWriter out = null;

    try {
        System.out.println("Entering" + " try statement");

        out = new PrintWriter(new FileWriter("OutFile.txt"));
        for (int i = 0; i < SIZE; i++) {
            out.println("Value at: " + i + " = " + list.get(i));
        }
    } catch (IndexOutOfBoundsException e) {
        System.err.println("Caught IndexOutOfBoundsException: "
                           +  e.getMessage());
                                 
    } catch (IOException e) {
        System.err.println("Caught IOException: " +  e.getMessage());
                                 
    } finally {
        if (out != null) {
            System.out.println("Closing PrintWriter");
            out.close();
        } 
        else {
            System.out.println("PrintWriter not open");
        }
    }
}

如前所述,此方法的try塊有三種不同的退出可能性,這是其中兩個。

try語句中的代碼失敗并引發(fā)異常,這可能是由new FileWriter語句引起的IOException或由for循環(huán)中的錯誤索引值引起的IndexOutOfBoundsException。

一切都成功,try語句正常退出。

場景1:發(fā)生異常

創(chuàng)建FileWriter的語句可能由于多種原因而失敗,例如,如果程序無法創(chuàng)建或?qū)懭胫甘镜奈募?,則FileWriter的構(gòu)造函數(shù)將拋出IOException

當(dāng)FileWriter拋出IOException時,運行時系統(tǒng)立即停止執(zhí)行try塊,正在執(zhí)行的方法調(diào)用未完成,然后,運行時系統(tǒng)開始在方法調(diào)用堆棧的頂部搜索適當(dāng)?shù)漠惓L幚沓绦颉T诖耸纠?,發(fā)生IOException時,FileWriter構(gòu)造函數(shù)位于調(diào)用堆棧的頂部,但是,FileWriter構(gòu)造函數(shù)沒有適當(dāng)?shù)漠惓L幚沓绦颍虼诉\行時系統(tǒng)在方法調(diào)用堆棧中檢查下一個方法 — writeList方法,writeList方法有兩個異常處理程序:一個用于IOException,另一個用于IndexOutOfBoundsException。

運行時系統(tǒng)按照它們在try語句之后出現(xiàn)的順序檢查writeList的處理程序,第一個異常處理程序的參數(shù)是IndexOutOfBoundsException,這與拋出的異常類型不匹配,因此運行時系統(tǒng)會檢查下一個異常處理程序 — IOException,這與拋出的異常類型相匹配,因此運行時系統(tǒng)結(jié)束搜索適當(dāng)?shù)漠惓L幚沓绦?,既然運行時已找到適當(dāng)?shù)奶幚沓绦?,那么?zhí)行該catch塊中的代碼。

異常處理程序執(zhí)行后,運行時系統(tǒng)將控制權(quán)傳遞給finally塊,無論上面捕獲的異常如何,finally塊中的代碼都會執(zhí)行,在這種情況下,FileWriter從未打開過,不需要關(guān)閉,在finally塊完成執(zhí)行后,程序繼續(xù)執(zhí)行finally塊之后的第一個語句。

這是拋出IOException時出現(xiàn)的ListOfNumbers程序的完整輸出。

Entering try statement
Caught IOException: OutFile.txt
PrintWriter not open

以下清單中的后加*號的代碼顯示了在此方案中執(zhí)行的語句:

public void writeList() {
   PrintWriter out = null; //******

    try {
        System.out.println("Entering try statement"); //*******
        out = new PrintWriter(new FileWriter("OutFile.txt")); //******
        for (int i = 0; i < SIZE; i++)
            out.println("Value at: " + i + " = " + list.get(i));
                               
    } catch (IndexOutOfBoundsException e) {
        System.err.println("Caught IndexOutOfBoundsException: "
                           + e.getMessage());
                                 
    } catch (IOException e) {
        System.err.println("Caught IOException: " + e.getMessage()); //*****
    } finally {
        if (out != null) { //*****
            System.out.println("Closing PrintWriter");
            out.close();
        } 
        else {
            System.out.println("PrintWriter not open"); /******
        }
    }
}
場景2:try塊正常退出

在這種情況下,try塊范圍內(nèi)的所有語句都成功執(zhí)行,并且不會拋出異常,執(zhí)行在try塊的末尾結(jié)束,運行時系統(tǒng)將控制傳遞給finally塊,因為一切都成功了,所以當(dāng)控制到達(dá)finally塊時,PrintWriter會打開,這會關(guān)閉PrintWriter,同樣,在finally塊完成執(zhí)行之后,程序繼續(xù)執(zhí)行finally塊之后的第一個語句。

當(dāng)沒有拋出異常時,這是ListOfNumbers程序的輸出。

Entering try statement
Closing PrintWriter

以下示例中的加*號的代碼顯示了在此方案中執(zhí)行的語句。

public void writeList() {
    PrintWriter out = null; //*****
    try {
        System.out.println("Entering try statement"); //******
        out = new PrintWriter(new FileWriter("OutFile.txt")); //******
        for (int i = 0; i < SIZE; i++) //******
            out.println("Value at: " + i + " = " + list.get(i)); //******
                  
    } catch (IndexOutOfBoundsException e) {
        System.err.println("Caught IndexOutOfBoundsException: "
                           + e.getMessage());

    } catch (IOException e) {
        System.err.println("Caught IOException: " + e.getMessage());
                                 
    } finally {
        if (out != null) { //******
            System.out.println("Closing PrintWriter"); //******
            out.close(); //*******
        } 
        else {
            System.out.println("PrintWriter not open");
        }
    }
}
上一篇:捕獲或指定要求 下一篇:如何拋出異常

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/77482.html

相關(guān)文章

  • Java? 教程捕獲或指定要求)

    捕獲或指定要求 有效的Java編程語言代碼必須遵守捕獲或指定需求,這意味著可能拋出某些異常的代碼必須包含以下任一項: 捕獲異常的try語句,try必須為異常提供處理程序,如捕獲和處理異常中所述。 一種方法,指定它可以拋出異常,該方法必須提供一個throws子句,列出異常,如通過方法拋出指定異常中所述。 不符合捕獲或指定要求的代碼將無法編譯。 并非所有異常都受捕獲或指定要求的約束,為了理解原因,...

    wanglu1209 評論0 收藏0
  • Java? 教程異常的優(yōu)點)

    異常的優(yōu)點 現(xiàn)在你已經(jīng)知道了什么是異常以及如何使用它們,現(xiàn)在是時候了解在程序中使用異常的優(yōu)勢了。 優(yōu)點1:將錯誤處理代碼與常規(guī)代碼分開 異常提供了從程序的主邏輯中分離異常發(fā)生時應(yīng)該做什么的細(xì)節(jié)的方法,在傳統(tǒng)的編程中,錯誤檢測、報告和處理通常會導(dǎo)致混亂的意大利面代碼,例如,考慮這里的偽代碼方法將整個文件讀入內(nèi)存。 readFile { open the file; determine...

    jollywing 評論0 收藏0
  • Java? 教程(如何拋出異常

    如何拋出異常 在捕獲異常之前,某些代碼必須拋出一個,任何代碼都可能拋出異常:你的代碼,來自其他人編寫的包中的代碼,例如Java平臺附帶的包或Java運行時環(huán)境,無論拋出什么異常,它總是使用throw語句拋出。 你可能已經(jīng)注意到,Java平臺提供了許多異常類,所有類都是Throwable類的后代,并且所有類都允許程序區(qū)分在程序執(zhí)行期間可能發(fā)生的各種類型的異常。 你還可以創(chuàng)建自己的異常類來表示你編寫的...

    zhangwang 評論0 收藏0
  • Java? 教程(什么是異常?)

    什么是異常? exception一詞是exceptional event這一短語的簡寫。 定義:異常是在程序執(zhí)行期間發(fā)生的事件,它會破壞程序指令的正常流程。 當(dāng)方法中發(fā)生錯誤時,該方法會創(chuàng)建一個對象并將其交給運行時系統(tǒng),該對象稱為異常對象,包含有關(guān)錯誤的信息,包括錯誤發(fā)生時的類型和程序狀態(tài),創(chuàng)建異常對象并將其交給運行時系統(tǒng)稱為拋出異常。 在方法拋出異常后,運行時系統(tǒng)會嘗試查找處理它的內(nèi)容,處理異常...

    Enlightenment 評論0 收藏0
  • Java? 教程(目錄)

    Java? 教程 Java教程是為JDK 8編寫的,本頁面中描述的示例和實踐沒有利用在后續(xù)版本中引入的改進(jìn)。 Java教程是希望使用Java編程語言創(chuàng)建應(yīng)用程序的程序員的實用指南,其中包括數(shù)百個完整的工作示例和數(shù)十個課程,相關(guān)課程組被組織成教程。 覆蓋基礎(chǔ)知識的路徑 這些教程以書籍的形式提供,如Java教程,第六版,前往Amazon.com購買。 入門 介紹Java技術(shù)和安裝Java開發(fā)軟件并使用...

    lifesimple 評論0 收藏0

發(fā)表評論

0條評論

Yujiaao

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<