如何避免重复复杂的catch块
我有这个代码:
try { do_stuff(); return do_more_stuff(); } catch (UnsupportedEncodingException e) { throw CustomException.programmer_error(e); } catch (ProtocolException e) { throw CustomException.programmer_error(e); } catch (MalformedURLException e) { throw CustomException.programmer_error(e); } catch (SocketTimeoutException e) { throw new CustomException(e); } catch (IOException e) { throw CustomException.unexpected_error(e); }
我现在需要在另一个类似的函数中拥有所有这些catch块。 避免重复的最佳方法是什么?
请注意,两个try块中的代码不是很相似。
此外,我无法真正把这些捕获量提升到更高的水平。
请注意,我宁愿避免:
try { do_stuff(); return do_more_stuff(); } catch (Exception e) { handle_exception_via_rtti(e); }
我个人试着去做
do_stuff(); return do_more_stuff();
部分符合更一般的格式以应用策略(作为模式)。
然后你可以重构所有你称之为这种块的地方,这样他们就可以调用一个更通用的块(捕获只被放置一次)。
请注意,我宁愿避免:
然后要么只是忍受它,要么等到JDK7附带Multicatch,这样你就可以重写:
try { do_stuff(); return do_more_stuff(); } catch (UnsupportedEncodingException | ProtocolException | MalformedURLException e) { throw CustomException.programmer_error(e); } catch (SocketTimeoutException e) { throw new CustomException(e); } catch (IOException e) { throw CustomException.unexpected_error(e); }
您也可以将其移动到CustomException
的构造函数中并执行(讨厌的)全局捕获,但是您需要添加一堆(讨厌的) if/else
块来确定exception原因的类型。 总而言之,我只是喜欢坚持你已经做过的方式。
更新 :另一种方法是拆分/重构行,这些行可能CustomException
exception作为单独的任务抛出到抛出CustomException
另一个方法块中。 例如
try { do_stuff_with_encoding(); do_stuff_with_url(); do_stuff_with_ws(); // ... return do_more_stuff(); } catch (SocketTimeoutException e) { throw new CustomException(e); } catch (IOException e) { throw CustomException.unexpected_error(e); } ... public SomeObject do_stuff_with_encoding() throws CustomException { try { do_stuff(); } catch (UnsupportedEncodingException e) { throw CustomException.programmer_error(e); } } public SomeObject do_stuff_with_url() throws CustomException { try { do_stuff(); } catch (MalformedURLException e) { throw CustomException.programmer_error(e); } } public SomeObject do_stuff_with_ws() throws CustomException { try { do_stuff(); } catch (ProtocolException e) { throw CustomException.programmer_error(e); } }
这取决于do_stuff
和do_more_stuff
抛出已检查exception的原因。 他们这样做是为了强迫用户处理exception吗? 如果是,那么你试图避免:
try { do_stuff(); return do_more_stuff(); } catch (Exception e) { handle_exception_via_rtti(e); }
是一件好事。
如果您的代码只捕获Exception
,而do_stuff
和do_more_stuff
稍后会添加额外的exception,您可能永远不会知道更改以及您的代码现在可能出错的事实。
因此,您可能不得不处理抛出厨房水槽并处理所有这些exception,除非方法可以切换到未经检查的exception。
另一方面,如果方法抛出已检查的exception只是因为程序员在处理它们时懒得而只是想要推卸责任,也许你是从错误的角度看待这个。
如何引入可以子类化的通用Action类:
public class Action { public void runWithHandlers() throws Exception { try { run(); } catch (UnsupportedEncodingException e) { throw CustomException.programmer_error(e); } catch (ProtocolException e) { throw CustomException.programmer_error(e); } catch (MalformedURLException e) { throw CustomException.programmer_error(e); } catch (SocketTimeoutException e) { throw new CustomException(e); } catch (IOException e) { throw CustomException.unexpected_error(e); } } public void run() throws Exception { // TODO subclasses of Action must implement this } }
然后在代码中的其他地方实例化Action的一个子类并调用runWithHandlers():
new MyAction().runWithHandlers();
如果你能买得起Scala,请查看它:你可以在catch块中模式匹配exception。 请参阅Scala for Java Refugees第4部分:模式匹配和例外 。