- 浏览: 107228 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
习惯在马桶上思考:
续在哪里啊
Spring 3.0 OXM - Spring 3.0 框架新特性 -
卖火柴的老特工:
学习了
为什么要自定义异常 -
xiarilian12:
受教了!呵呵~~~
REST是什么[精品] -
tidelgl:
不知道3.0对泛型的扫描注入支持完善了没有,现在用2.5有点抓 ...
详解 Spring 3.0 基于 Annotation 的依赖注入实现
Before you read this text, it is a good idea to have read the text "Fail Safe Exception Handling".
Correct exception handling code can be tedious to write. Try-catch blocks also clutter the code and makes it harder to read. Look at the example below:
Input input = null; IOException processException = null; try{ input = new FileInputStream(fileName); //...process input stream... } catch (IOException e) { processException = e; } finally { if(input != null){ try { input.close(); } catch(IOException e){ if(processException != null){ throw new MyException(processException, e, "Error message..." + fileName); } else { throw new MyException(e, "Error closing InputStream for file " + fileName; } } } if(processException != null){ throw new MyException(processException, "Error processing InputStream for file " + fileName; }
In this example no exceptions are lost. If an exception is thrown from within the try block, and another exception is thrown from the input.close() call in the finally block, both exceptions are preserved in the MyException instance, and propagated up the call stack.
That is how much code it takes to handle the processing of an input stream without any exceptions being lost. In fact it only even catches IOExceptions. RuntimeExceptions thrown from the try-block are not preserved, if the input.close() call also throws an exception. Isn't it ugly? Isn't it hard to read what is actually going on? Would you remember to write all that code everytime you process an input stream?
Luckily there is a simple design pattern, the Template Method, that can help you get the exception handling right everytime, without ever seeing or writing it in your code. Well, maybe you will have to write it once, but that's it.
What you will do is to put all the exception handling code inside a template. The template is just a normal class. Here is a template for the above input stream exception handling:
public abstract class InputStreamProcessingTemplate { public void process(String fileName){ IOException processException = null; InputStream input = null; try{ input = new FileInputStream(fileName); doProcess(input); } catch (IOException e) { processException = e; } finally { if(input != null){ try { input.close(); } catch(IOException e){ if(processException != null){ throw new MyException(processException, e, "Error message..." + fileName); } else { throw new MyException(e, "Error closing InputStream for file " + fileName; } } } if(processException != null){ throw new MyException(processException, "Error processing InputStream for file " + fileName; } } //override this method in a subclass, to process the stream. public abstract void doProcess(InputStream input) throws IOException; }
All the exception handling is encapulated inside the InputStreamProcessingTemplate class. Notice how the process() method calls the doProcess() method inside the try-catch block. You will use the template by subclassing it, and overriding the doProcess() method. To do this, you could write:
new InputStreamProcessingTemplate(){ public void doProcess(InputStream input) throws IOException{ int inChar = input.read(); while(inChar !- -1){ //do something with the chars... } } }.process("someFile.txt");
This example creates an anonymous subclass of the InputStreamProcessingTemplate class, instantiates an instance of the subclass, and calls its process() method.
This is a lot simpler to write, and easier to read. Only the domain logic is visible in the code. The compiler will check that you have extended the InputStreamProcessingTemplate correctly. You will typically also get more help from your IDE's code completion when writing it, because the IDE will recognize both the doProcess() and process() methods.
You can now reuse the InputStreamProcessingTemplate in any place in your code where you need to process a file input stream. You can easily modify the template to work for all input streams and not just files.
Using Interfaces Instead of Subclassing
Instead of subclassing the InputStreamProcessingTempate you could rewrite it to take an instance of an InputStreamProcessor interface. Here is how it could look:
public interface InputStreamProcessor { public void process(InputStream input) throws IOException; } public class InputStreamProcessingTemplate { public void process(String fileName, InputStreamProcessor processor){ IOException processException = null; InputStream input = null; try{ input = new FileInputStream(fileName); processor.process(input); } catch (IOException e) { processException = e; } finally { if(input != null){ try { input.close(); } catch(IOException e){ if(processException != null){ throw new MyException(processException, e, "Error message..." + fileName; } else { throw new MyException(e, "Error closing InputStream for file " + fileName); } } } if(processException != null){ throw new MyException(processException, "Error processing InputStream for file " + fileName; } } }
Notice the extra parameter in the template's process() method. This is the InputStreamProcessor, which is called from inside the try block (processor.process(input)). Using this template would look like this:
new InputStreamProcessingTemplate() .process("someFile.txt", new InputStreamProcessor(){ public void process(InputStream input) throws IOException{ int inChar = input.read(); while(inChar !- -1){ //do something with the chars... } } });
It doesn't look much different from the previous usage, except the call to the InputStreamProcessingTemplate.process() method is now closer to the top of the code. This may be easier to read.
Static Template Methods
It is also possible to implement the template method as a static method. This way you don't need to instantiate the template as an object every time you call it. Here is how the InputStreamProcessingTemplate would look as a static method:
public class InputStreamProcessingTemplate { public static void process(String fileName, InputStreamProcessor processor){ IOException processException = null; InputStream input = null; try{ input = new FileInputStream(fileName); processor.process(input); } catch (IOException e) { processException = e; } finally { if(input != null){ try { input.close(); } catch(IOException e){ if(processException != null){ throw new MyException(processException, e, "Error message..." + fileName); } else { throw new MyException(e, "Error closing InputStream for file " + fileName; } } } if(processException != null){ throw new MyException(processException, "Error processing InputStream for file " + fileName; } } }
The process(...) method is simply made static. Here is how it looks to call the method:
InputStreamProcessingTemplate.process("someFile.txt", new InputStreamProcessor(){ public void process(InputStream input) throws IOException{ int inChar = input.read(); while(inChar !- -1){ //do something with the chars... } } });
Notice how the call to the template's process() method is now a static method call.
Summary
Exception handling templates are a simple yet powerful mechanism that can increase the quality and readability of your code. It also increases your productivity, since you have much less code to write, and less to worry about. Exceptions are handled by the templates. And, if you need to improve the exception handling later in the development process, you only have a single spot to change it in: The exception handling template.
The Template Method design pattern can be used for other purposes than exception handling. The iteration of the input stream could also have been put into a template. The iteration of a ResultSet in JDBC could be put into a template. The correct execution of a transaction in JDBC could be put into a template. The possibilities are endless.
Context reuse and templates are also discussed in the article Code Reuse: Context and Action Reuse.
发表评论
-
java的几种对象(PO,VO,DAO,BO,POJO,DTO)解释
2011-02-23 14:58 1261... -
为什么要自定义异常
2010-12-12 15:27 2038为什么要自定义异常? 自定义异常是为了设置异常链的起点。 ... -
REST与SOAP区别
2010-12-12 14:51 1342如果你需要使用WSDL来发布你的服务,或者你需要一些安全功能如 ... -
有包类调用无包类(java反射机制运用)
2010-12-03 17:58 1225try { //Class[] stri ... -
【转载】反面模式(Anti-pattern)
2010-12-03 11:02 1052[目录] [1. 已知的反面模式] [1.1 组织结构的反 ... -
软件公司的岗位职责
2010-10-29 09:47 1048软件公司的岗位职责 ... -
中文参数编码后传递依然乱码解决方法(java.net.URLEncoder.encode)
2010-10-27 16:35 2779使用java.net.URLEncoder.encode()可 ... -
log4j日志处理
2010-10-26 11:07 11041.log4j与Jakarta Commons Logging ... -
Log4j每天或每个月产生一个日志文件
2010-08-16 10:34 2108Log4j每天或每个月产生一个日志文件 我们开发的B/ ... -
REST是什么[精品]
2010-07-07 09:41 1278概述 REST是英文Repr ... -
对REST中无状态(stateless)的理解
2010-07-06 17:52 3444无状态指的是任意一个Web请求必须完全与其他请求隔离,当请求端 ... -
REST及RESTful的实现
2010-07-06 16:08 828REST及RESTful的实现 ... -
为什么Java 中要使用 Checked Exceptions?
2010-06-24 16:14 765设计中常被忽略的一块:http://www.iteye.com ... -
通过request.getContextPath获取绝对路径
2010-06-07 11:45 4077<%=request.getContextPath()% ...
相关推荐
例如,使用Log4j或SLF4J进行日志记录,使用Exception Handling来捕获和处理异常。 7. **性能优化**:后台模板可能集成了缓存机制,如Redis或Memcached,以提升数据读取速度。同时,使用Gzip压缩、CDN内容分发网络等...
C++中的模板(templates)和异常处理(exception handling)也是需要特别关注的部分,因为这些在Java中也有相应的概念,但实现和用法可能有所不同。 由于文件提到文档目前还处于草案阶段,建议Java程序员在学习C和...
4. **异常处理(Exception Handling)** C++支持异常处理机制,通过 `try`、`catch` 和 `throw` 关键字来捕获和处理运行时错误。理解何时和如何使用异常处理能帮助编写健壮的代码。 5. **模板(Templates)** ...
5. **异常处理 (Exception Handling):** - 配置异常处理策略,如忽略模板加载错误等。 #### 六、其他说明 1. **变量 (Variables):** - 如何声明和使用变量。 2. **字符编码 (Character Encoding):** - 设置...
7. **异常处理(Exception Handling)**:Struts2提供了全局和局部的异常处理机制,可以优雅地处理程序中的错误和异常。 8. **国际化(Internationalization, I18N)**:Struts2支持多语言,方便开发面向全球用户的...
3. **异常处理(Exception Handling)**:异常处理是C++中用于错误处理的一种机制,通过try、catch和throw关键字,可以在程序运行时捕获和处理错误,保证程序的健壮性。 4. **命名空间(Namespaces)**:命名空间是...
在移动QQ源码中,你可能会看到C++的一些核心特性,如类(class)、对象(object)、继承(inheritance)、多态(polymorphism)等面向对象编程概念,以及模板(templates)、异常处理(exception handling)、STL...
7. **Exception Handling**:使用 `@ExceptionHandler` 注解可以定义全局或特定异常的处理逻辑,返回自定义的错误信息。 8. **HATEOAS**:HATEOAS(Hypermedia as the Engine of Application State)是 REST 架构的...
4. **异常处理(Exception Handling)**:当满足特定条件时触发警报可能涉及到异常处理。在C++中,可以使用`try-catch`块来捕获和处理可能出现的异常。如果数据不符合预期或存在错误,抛出一个异常并由相应的`catch`...
C++的特点包括类(classes)、模板(templates)、异常处理(exception handling)以及STL(Standard Template Library),这些特性使得C++能够创建高效且易于维护的代码。 Codechef Long Challenge的题目涵盖了...
异常处理(Exception Handling)也是C++中处理错误和异常情况的重要机制。 总之,“2020CCE.class”这个文件名可能代表了一次关于C++编程的教育活动,其中涵盖了面向对象编程的核心概念。通过学习和理解类(Class)...