jdk1.7中try-with-resources語法糖詳解

首先回憶一下jdk1.7以前,咱們要經過流讀取文件時,代碼要怎樣寫?java

假設本地文件系統d盤下有一個in.txt文件,代碼以下:編碼

FileInputStream in = null;
		try {
			in = new FileInputStream("d:/in.txt");
		} catch(Exception e) {
			System.out.println(e.getMessage());
			throw new RuntimeException("try塊中產生了異常",e);
		} finally {
			if (in != null)
				in.close();
		}

此時試想一個問題:若是try塊中new FileInputStream拋出了異常,在finally塊中調用close方法時也拋出了異常,那麼最終拋給上層的到底是哪一個異常?spa

答案是:拋給上層的是close方法產生的異常。code

可是很明顯,咱們但願的是把catch塊中捕獲的異常進行處理後,繼續向上拋出,可結果卻由於close方法產生異常而丟失了咱們預期的異常。對象

針對此問題,解決方案是:調用in.close()時再次使用try-catch塊包裹,代碼以下:接口

FileInputStream in = null;
		try {
			in = new FileInputStream("d:/in.txt");
		} catch(Exception e) {
			System.out.println(e.getMessage());
			throw new RuntimeException("try塊中產生了異常",e);
		} finally {
			if (in != null)
				try {
					in.close();
				}catch(IOException e) {
					e.printStackTrace();
				}
		}

至此,問題已經獲得完美解決。可是,每次處理IO問題時都要編碼重複且複雜的代碼是否是很繁瑣?因而,jdk1.7推出了叫作try-with-resources的語法糖。則上面的代碼能夠改下以下:get

/**
		 * try-with-resource語法糖
		 */
		try (FileInputStream in = new FileInputStream("d:/in.txt")) {
			// do something
		} catch(Exception e) {
			System.out.println("message:"+e.getMessage());
			throw new RuntimeException("try塊中產生了異常",e);
		}

try()中的類型必須實現AutoCloseable接口(jdk1.7開始引入了此接口,做爲Closeable接口的父接口)。it

此結構的執行順序爲:io

  1. 執行try快中語句class

  2. 調用try()中的全部對象的close()方法

  3. 若是try塊產生異常,則執行catch中的邏輯

  4. 若是存在finally塊,則執行其邏輯

另外,還須要注意的是:

若是try塊產生了異常,則會忽略close產生的異常(若是真的產生異常的話);不然纔會拋出close產生的異常(若是真的產生異常的話)。

所以,try-with-resources語法糖等價於如下寫法:

        // 此處的try至關於
        // try (FileInputStream in = new FileInputStream("d:/in.txt"))
        try {
            InputStream in = null;
            /**
             * 如下try-catch能夠理解爲語法糖自動生成的代碼
             */
            try {
                in = new FileInputStream("d:/in.txt");
                // do something
                in.close();
            } catch (IOException e) {
                if (in != null)
                    try {
                        in.close();
                    } catch (IOException ee) {
                        if (e != ee)
                            e.addSuppressed(ee);
                    }
                throw e;
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
            throw new RuntimeException("try塊中產生了異常", e);
        }
相關文章
相關標籤/搜索