Problem
如果有寫到CLI的tool,使用Scanner物件是很平常的事情,因此應會遇到是否該close Scanner物件的問題。假如有兩個類別都會使用到使用System.in的Scanner,先close的就會讓後面的發生問題。
Solutions
閱讀幾篇文章後,有以下做法:
- 不理它,反正不會造成memory leak。
- 使用Decorator樣式,將System.in包裝在不會真的close的InputStream中。
- 使用Singleton樣式,大家都用同一個Global Scanner。
第一個做法對於寫code有潔癖的人來說,不會去使用的。而第二和第三個做法,以單元測試方便性來說與,我比較偏愛Decorator方式;使用Singleton的作法,還要考慮到底是誰負責close。如果大家都說好,你可以透過shutdown hook去close。
分享decorator作法,參考apache common io程式碼:
public class CloseShieldInputStream extends ProxyInputStream { /** * Creates a proxy that shields the given input stream from being * closed. * * @param in underlying input stream */ public CloseShieldInputStream(InputStream in) { super(in); } /** * Replaces the underlying input stream with a {@link ClosedInputStream} * sentinel. The original input stream will remain open, but this proxy * will appear closed. */ public void close() { in = new ClosedInputStream(); } }
Client可以這樣使用:
try( Scanner scanner = new Scanner(new CloseShieldInputStream(System.in))){ // some operations }
留言
張貼留言