2010-10-22 32 views
1

由於我公司的使用Eclipse和使用Eclipse的代碼自動修復的政策,下面的代碼模式過度地出現在代碼庫:如何重構在Java中關閉流?

InputStream is = null; 
try { 
    is = url.openConnection().getInputStream(); 
    // ..... 
} catch (IOException e) { 
    // handle error 
} finally { 
    if (is != null) { 
     try { 
      is.close(); 
     } catch (IOException e) { 
      // handle error 
     } 
    } 
} 

IMO這是非常的fugly,難以閱讀,尤其是最後塊內的部分(是否真的需要捕獲2個IOException異常?)。無論如何簡化代碼,使其看起來更清潔?

+0

請注意,我不能使用外部庫,如Apache IOUtils,除非它經過多個實體的測試和批准 – david 2010-10-22 01:33:35

+5

使用Apache IOUtils的關鍵在於它已經被無數其他人測試過了。這就是說,我感到你的痛苦。在您的組織內部IOUtils經過測試和認可*一次*是否值得?因此您可以在所有項目中使用它? – 2010-10-22 01:36:27

+0

如果只有這樣簡單的生活......我必須通過多層次的管理和繁文to節才能讓相關工作組看到它。我們仍然堅持使用JDK1.4.2,這是因爲已經退役的軟件存在'遺留'問題 – david 2010-10-22 01:43:14

回答

1

看到這個question,使用closeQuietly()解決方案。

InputStream is = null; 
try { 
    is = url.openConnection().getInputStream(); 
    // ..... 
} catch (IOException e) { 
    // handle error 
} finally { 
    IoUtils.closeQuietly(is); 
} 

// stolen from the cited question above 
public class IoUtils { 

    public static closeQuietly (Closeable closeable) { 
    try { 
     closeable.close(); 
    } catch (IOException logAndContinue) { 
     ... 
    } 
    } 
} 

或等待JDK7's ARM blocks

1

首先,關於使用IOUtils - 可能值得一試,告訴上司他們可能使用的應用程序服務器/ Java運行時環境使用IOUtils以及類似的庫本身。所以本質上你不會在你的架構中引入新的組件。

二,不,不是真的。除了編寫自己的實用程序來模擬IOUtils的closeQuietly方法之外,沒有任何辦法可以解決這個問題。現在

+0

嘿,如果closeQuietly是開源,請將其複製到您的項目中。 – 2010-10-22 02:09:36

+0

...而可重複使用和模塊化的發明者高興地在他的墳墓裏休息...... – Isaac 2010-10-22 02:28:21

+0

close靜靜地忽略了異常。這從來不是一個好習慣。此外,大衛想要「處理錯誤」。 – mschonaker 2010-10-22 05:51:21

1
public class Util { 
    public static void closeStream(inputStream is) { 
     if (is != null) { 
      try { 
       is.close(); 
      } catch (IOException e) { 
       // log something 
     } 
    } 
} 

你的代碼是

InputStream is = null; 
try { 
    is = url.openConnection().getInputStream(); 
    // ..... 
} catch (IOException e) { 
    // handle error 
} finally { 
    Util.closeStream(is); 
} 

沒有太多事情可做的IOException異常在catch可能有一些特殊的處理。

+0

我喜歡這個,但我會傾向於更進一步,並創建Util.openStream(url),以便調用者不在2個不同的抽象層次上操作。 – 2010-10-22 14:33:03

3

爲什麼什麼東西?這是工作代碼。這是正確的。

保留它。

+0

對於反指稱,http://www.klocwork.com/blog/2010/10/refactoring-if-it-aint-broken-dont-fix-it/ – andersoj 2010-10-22 10:14:52

+0

他沒有問,「我該怎麼辦「他問,」我該怎麼做。「 – 2010-10-22 17:44:04

+0

我在問爲什麼。爲什麼應該有一個干擾工作代碼的預算?在那工作*生成*代碼。我將生成的代碼視爲目標代碼,我不會惹惱它。 – EJP 2010-10-23 00:53:02

0

您可以定義是這樣的地方:

private static interface InputStreamCallback { 

    public void doIt(InputStream is) throws IOException; 

} 

private void with(InputStreamCallback cb) { 

    InputStream is = null; 

    // Creational code. Possibly adding an argument 

    try { 
     cb.doIt(is); 
    } catch (IOException e) { 
     // handle error or rethrow. 
     // If rethrow add throws to method spec. 
    } finally { 
     if (is != null) { 
      try { 
       is.close(); 
      } catch (IOException e) { 
       // handle error or rethrow. 
      } 
     } 
    } 
} 

並調用這樣的代碼:

with(new InputStreamCallback() { 

    @Override 
    public void doIt(InputStream is) throws IOException { 
     is = url.openConnection().getInputStream(); 
     // ..... 
    } 

}); 

如果你在一個輔助類方法static聲明,那麼你甚至可以做一個它的import static

有一個缺點。您需要聲明url final。

編輯:創建代碼不是重點。你可以用幾種方法來安排它。回調是重點。你可以隔離你在那裏需要做什麼。