如何避免重复复杂的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原因的类型。 总而言之,我只是喜欢坚持你已经做过的方式。

更新 :另一种方法是拆分/重构行,这些行可能CustomExceptionexception作为单独的任务抛出到抛出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_stuffdo_more_stuff抛出已检查exception的原因。 他们这样做是为了强迫用户处理exception吗? 如果是,那么你试图避免:

 try { do_stuff(); return do_more_stuff(); } catch (Exception e) { handle_exception_via_rtti(e); } 

是一件好事。

如果您的代码只捕获Exception ,而do_stuffdo_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部分:模式匹配和例外 。