Atitit.异常的设计原理与 策略处理 java 最佳实践 p93

1 异常方面的使用准则,答案是::
2

1.1 普通项目优先使用异常取代返回值,如果开发类库方面的项目,最好异常机制与返回值都提供,由调用者决定使用哪种方式。。
2

1.2 优先把异常抛出到上层处理。。异常本身就是为了方便把异常情况抛出到上层处理。。
2

1.3 对于 HYPERLINK \l _Toc6222 方法调用结果异常情况返回策略,最终会有四种策略状况,
2

1.4 返回null  还是异常??
2

2 异常的由来与设计
3

2.1 为什么使用异常
3

2.2 用throw抛出一个异常到catch子句中与通过函数调用传递一个参数两者基本相同。
4

2.3 S E H的主要动机
4

2.4 RuntimeException跟checked Exception
4

2.5 要不要使用checked Exception
5

2.6 checked Exception 的缺点
5

2.7 Base类and 扩展class 抛出的特别的异常不一样的解决之道
5

2.8 【异常处理框架】
5

3 Exception业务流程控制 可以借鉴一下)
6

4 4. 常见的捕获异常后的处理策略
2 7

4.1 check异常转换为runtime 异常
7

4.2 checked Exception 转换 re
8

4.3 丢出新异常D,可以让它从已有的异常中继承,
8

4.4 常见的捕获异常后的处理策略
9

4.5 转换为业务异常,抛出至上层处理(常用)
9

4.6 根据异常种类处理异常(常用)
9

4.7 事务rollback
9

4.8 日志记录,重新抛出
9

4.9 忽略异常(较少这样处理)
9

5 列举最常用的五种RuntimeException:    
9

5.1 下面是JDK API中列出的异常类: 除了RuntimeException以外的,都是checked Exception
10

5.2 Java异常类的层次结构
11

6 参考
13

1 异常方面的使用准则,答案是::

1.1 普通项目优先使用异常取代返回值,如果开发类库方面的项目,最好异常机制与返回值都提供,由调用者决定使用哪种方式。。

1.2 优先把异常抛出到上层处理。。异常本身就是为了方便把异常情况抛出到上层处理。。

当然根据一些特殊情况可以还有其他方式来处理。。但并非将来的主流趋势...需要注意。。

作者:: 老哇的爪子 Attilax 艾龙,  EMAIL:1466519819@qq.com

转载请注明来源: http://blog.csdn.net/attilax

1.3 对于方法调用结果异常情况返回策略,最终会有四种策略状况,

抛出异常excepttion、返回特殊值、阻塞、超时
2

1.4 返回null  还是异常??

·

对于极其常见的错误案例,返回 null 而不是引发异常。 极其常见的错误案例可被视为常规控制流。 通过在这些情况下返回 null,可最大程度地减小对应用的性能产生的影响。

2  异常的由来与设计

任务与预先设定的规则不相符的情况都可以称之为异常。但凡业务逻辑操作,都会划定一些边界或规则,但是往往事与愿违,总会有调皮鬼来挑战系统的健壮性。这些调皮鬼包括: 



1、系统用户。用户并不都是知道潜规则的,比如用户的银行账户中只有100块钱,但是用户不查询就直接取200块。 

2、开发人员。码农有时候太过自信了,比如你在编写文件下载功能时忽略了文件有可能不存在这个分支流程。 

3、运行环境。软件系统也是要靠天吃饭的,谁都保不准网络一直畅通,硬盘一直稳定。

2.1 为什么使用异常

对C程序来说,使用Error Code就可以了,为什么还要引入异常?因为异常不能被忽略。如果一个函数通过设置一个状态变量或返回错误代码来表示一个异常状态,没有办法保证函数调用者将一定检测变量或测试错误代码。结果程序会从它遇到的异常状态继续运行,异常没有被捕获,程序立即会终止执行。

在C程序中,我们可以用int setjmp( jmp_buf env );和 void longjmp( jmp_buf env, int value );这2个函数来完成和异常处理相识的功能,但是MSDN中介绍了在C++中使用longjmp来调整stack时不能够对局部的对象调用析构函数,但是对C++程序来说,析构函数是重要的(我就一般都把对象的Delete放在析构函数中)。   <br>所以我们需要一个方法:①能够通知异常状态,又不能忽略这个通知,②并且Searching the stack以便找到异常代码时,③还要确保局部对象的析构函数被Call。而C++的异常处理刚好就是来解决这些问题的。</p>  <p>有的地方只有用异常才能解决问题,比如说,在当前上下文环境中,无法捕捉或确定的错误类型,我们就得用一个异常抛出到更大的上下文环境当中去。还有,异常处理的使用呢,可以使出错处理程序与“通常”代码分离开来,使代码更简洁更灵活。另外就是程序必不可少的健壮性了,异常处理往往在其中扮演着重要的角色。</p>

因为当函数返回时局部对象总是被释放,无论函数是如何退出的。(仅有一种例外就是当你调用longjmp时。Longjmp的这个缺点是C++率先支持异常处理的主要原因)

尽管C++首次引入异常的规范

尽管C++首次引入异常的规范,但是Java是强制实施"检查的异常"(Checked Exception)规范的唯一的主流语言

2.2 用throw抛出一个异常到catch子句中与通过函数调用传递一个参数两者基本相同。

这里面确有一些相同点,但是他们也存在着巨大的差异。</p>  <p>让我们先从相同点谈起。你传递函数参数与异常的途径可以是传值、传递引用或传递指针,这是相同的。但是当你传递参数和异常时,系统所要完成的操作过程则是完全不同的。产生这个差异的原因是:你调用函数时,程序的控制权最终还会返回到函数的调用处,但是当你抛出一个异常时,控制权永远不会回到抛出异常的地方。</p>

2.3 S E H的主要动机

微软在Wi n d o w s中引入S E H的主要动机是为了便于操作系统本身的开发。操作系统的开发人员使用S E H,使得系统更加强壮。我们也可以使用S E H,使我们的自己的程序更加强壮。    <br>使用S E H所造成的负担主要由编译程序来承担,而不是由操作系统承担。    <br>当异常块(exception block)出现时,编译程序要生成特殊的代码。编译程序必须产生一些表( t a b l e)来支持处理S E H的数据结构。    <br>编译程序还必须提供回调( c a l l b a c k)函数,操作系统可以调用这些函数,保证异常块被处理。    <br>编译程序还要负责准备栈结构和其他内部信息,供操作系统使用和参考。    <br>在编译程序中增加S E H支持不是一件容易的事。不同的编译程序厂商会以不同的方式实现S E H,这一点并不让人感到奇怪。幸亏我们可以不必考虑编译程序的实现细节,而只使用编译程序的S E H功能。(其实大多数编译程序厂商都采用微软建议的语法)

2.4 RuntimeException跟checked Exception

Java的Exception分为两类,一类是RuntimeException及其子类,另外一类就是checked Exception。Java要求函数对没有被catch处理掉的checked Exception,需要将其写在函数的声明部分

.net 只有RuntimeException

除了Error与RuntimeException,其他剩下的异常都是你需要关心的,而这些异常类统称为Checked Exception,至于Error与RuntimeException则被统称为Unchecked Exception.

2.5 要不要使用checked Exception

要使用....优点是流程clr,and ide能自动生成结构代码...

中建议在遇到可恢复的错误时采用checked异常,遇到不可恢复的异常时采用unchecked异常。

2.6 checked Exception 的缺点

支持Unchecked异常:

沿调用栈向上传播的Checked异常破坏了顶层的方法,因为这些方法必须声明抛出所有它们调用的方法抛出的异常

Check异常的抛出作为方法接口的一部分,这使得添加或移除早期版本中方法的异常难以实现。

2.7 Base类and 扩展class 抛出的特别的异常不一样的解决之道

可以在Base类的foo方法中加入抛出ExceptionB的声明,然而,这样就破坏了open-close原则。而且,有时我们没有办法去修改父类,比如当重载一个Jdk里的类的时候。

另一个可能的做法是在Extend的foo方法中catch住ExceptionB,然后构造一个ExceptionA并抛出。这是个可行的办法但也只是一个权宜之计。

2.8 【异常处理框架】

有问题我们就要解决问题,如果问题解决不了,那么就把问题的影响面降到最低。对于异常也是如此,为了提高健壮性,需要对于异常进行兼容。处理异常一个很重要的原则是不逃避,不歪曲。吞异常与提供错误的异常信息一样罪恶。对于异常的处理框架可以大致分为以下几点: 



1、异常类封装。根据异常产生的原因,我们把异常封装为两类,分别是业务逻辑异常(BusinessException)和系统编程异常(ProgramException),分类的目的是进行分类处理。 

2、异常检测类。这是产生异常的地方,包括了业务逻辑检测(对于不符合业务逻辑的情况封装异常抛出),还包括了对于底层异常的转化封装(比如将数据库操作产生的异常捕获并封装为ProgramException)。 

3、异常处理类。这是异常的终点,在此异常会以一种比较合适的方式对系统运维人员和系统的用户进行优雅的展示(比如记录日志或者页面提示)。

三、异常链

对于封装和转换的异常应该保留最底层原始的错误信息,即 root cause。只要向外抛出异常,就应该讲 root cause 异常抛出,这样最上层的异常就可以轻松获取底层异常信息。

在自定义异常体系的时候可以直接让异常存在支持异常链的构造器,对于不支持异常的异常,可以利用 Throwable 的 initCause() API 设置。

Exception业务流程控制 可以借鉴一下)

在使用UseCase来描述一个场景的时候,有一个主事件流和n个异常流。异常流可能发生在主事件流的过程,而try语句里面实现的是主事件流,而 catch里面实现的是异常流,在这里Exception不代表程序出现了异常或者错误,Exception只是面向对象化的业务逻辑控制方法。如果没有 明白这一点,那么我认为并没有真正明白应该怎么使用Java来正确的编程。 

      而我自己写的程序,会自定义大量的Exception类,个异常类,UserExistedException,抛出这个异常不代 表你插入动作失败,只说明你碰到一个分支流程,留待后面的catch中来处理这个分支流程。传统的程序员会写一个if else来处理,而一个合格的OOP程序员应该有意识的使用try catch 方式来区分主事件流和n个分支流程的处理,通过try catch,而不是if else来从代码上把不同的事件流隔离开来进行分别的代码撰写

·

4. 常见的捕获异常后的处理策略
2

4.1. 转换为业务异常,抛出至上层处理(常用)
2

4.2. 根据异常种类处理异常(常用)
3

4.3. 事务rollback
3

4.4. 日志记录,重新抛出
3

4.5. 忽略异常(很少这样处理)

从开发效率,灵活性考虑。。可以根据情况适当转换异常(不要使用返回值),继续抛出到sevlet层,这样可以::

方便aop filter对异常做处理。分层处理。

可以容易实现配置化的异常处理。。

4.1 check异常转换为runtime 异常

当check异常转换为runtime 异常时候的判断异常类型。。如果已经是re了,就不要转换了

try {

if(isOvertime_3month(last_check_time))

{

try {

String pcid=getPCid();

PropX px=new PropX(pathx.webAppPath()+"/0cfg/cfg.properties");

String url=px.getProperty("timer_check_authcode_url");

Map m=new HashMap();

m.put("pc_id", pcid);

url=new ParamX().varReplace(url, m, "@");

url=new ParamX().varReplace(url, px.getValList(), "%");

System.out.println(url);

String now_check_time=websitex.WebpageContent(url);

pref.put("now_check_time", now_check_time);

} catch (Exception e) {

throw  new OverTimeEx(e.getMessage());

}

}

} catch (Exception e) {

if (e.getCause() instanceof java.text.ParseException) {

throw new RuntimeException("ret from php date fmt err:"

+ e.getMessage());

}

if (e instanceof RuntimeException) {

throw (RuntimeException) e;

} else

throw new RuntimeException(e);

}

4.2 checked Exception 转换 re

为了避免在函数声明中写throws部分,在Java项目里面常常可以看到以下代码用来‘吞掉’Exception:

4.3 丢出新异常D,可以让它从已有的异常中继承,

[iii] 在“The Design and Evolution of C++”, Bjarne Stroustrup也提到,同样也基于对这个问题的考虑,c++没有“Static Checking”(checked exceptions)而是采用“Run time Checking”。而且Stroustrup建议,对于丢出新异常D,可以让它从已有的异常中继承,这样既不影响已有代码,新的代码也可以处理它。(这是Stroustrup在1990就作出的结论!)

4.4 常见的捕获异常后的处理策略

4.5 转换为业务异常,抛出至上层处理(常用)

从通信层异常转为业务异常,方便理解

主要是业务层处理与view层处理

一般是 catch 到 Lower Level Exception,但是向外抛出的却是 Higher Level Exception,对异常进行转换。

4.6 根据异常种类处理异常(常用)

4.7 事务rollback

能 rollback 的尽量 rollback

4.8 日志记录,重新抛出

主要用来统计分析稳定性情况,预警等

4.9 忽略异常(较少这样处理)

为了提升稳定性,需要冗余处理的时候,可以这样做。。。

列举最常用的五种RuntimeException:

这是JAVA认证考试中最常见的题目,事实上,runtime exception中最常见的,经常碰到的,也就5,6种,如下:

ArithmeticException

int a=0;

int b= 3/a;

ClassCastException:

Object x = new Integer(0);

System.out.println((String)x);

IndexOutOfBoundsException

    ArrayIndexOutOfBoundsException,

    StringIndexOutOfBoundsException

int [] numbers = { 1, 2, 3 };

int sum = numbers[3];

IllegalArgumentException

    NumberFormatException

int a = Interger.parseInt("test");

NullPointerExceptionextends

· 除了RuntimeException,其他继承自java.lang.Exception得异常统称为Checked Exception,他们有多少种呢?

5.1 下面是JDK API中列出的异常类:

除了RuntimeException以外的,都是checked Exception

java.lang.Object

  java.lang.Throwable

      java.lang.Exception

所有已实现的接口:

Serializable

直接已知子类:

AclNotFoundException, ActivationException, AlreadyBoundException, ApplicationException, AWTException, BackingStoreException, BadAttributeValueExpException, BadBinaryOpValueExpException, BadLocationException, BadStringOperationException, BrokenBarrierException, CertificateException, ClassNotFoundException, CloneNotSupportedException, DataFormatException, DatatypeConfigurationException, DestroyFailedException, ExecutionException, ExpandVetoException, FontFormatException, GeneralSecurityException, GSSException, IllegalAccessException, IllegalClassFormatException, InstantiationException, InterruptedException, IntrospectionException, InvalidApplicationException, InvalidMidiDataException, InvalidPreferencesFormatException, InvalidTargetObjectTypeException, InvocationTargetException, IOException, JAXBException, JMException, KeySelectorException, LastOwnerException, LineUnavailableException, MarshalException, MidiUnavailableException, MimeTypeParseException, MimeTypeParseException, NamingException, NoninvertibleTransformException, NoSuchFieldException, NoSuchMethodException, NotBoundException, NotOwnerException, ParseException, ParserConfigurationException, PrinterException, PrintException, PrivilegedActionException, PropertyVetoException, RefreshFailedException, RemarshalException, RuntimeException, SAXException, ScriptException, ServerNotActiveException, SOAPException, SQLException, TimeoutException, TooManyListenersException, TransformerException, TransformException, UnmodifiableClassException, UnsupportedAudioFileException, UnsupportedCallbackException, UnsupportedFlavorException, UnsupportedLookAndFeelException, URIReferenceException, URISyntaxException, UserException, XAException, XMLParseException, XMLSignatureException, XMLStreamException, XPathException

5.2 Java异常类的层次结构

图中红色部分为受检查异常。它们必须被捕获,或者在函数中声明为抛出该异常。

参考

Anders Hejlsberg论为什么不在c#引入类似java的checked exceptions - 产品和技术 - 赛迪网.htm

C++处理异常技巧.htm

[转载]JAVA 的checked异常和unchecked异常_4527_新浪博客.htm

Atitit.部分错误异常处理框架atiPartErr 的总结.doc

Atitit.常见的异常处理策略总结.doc

Atitit.java 异常的使用总结最佳实践 p56.doc (frm Vo8f)

Atitit.常见的捕获异常后的处理策略总结

Atitit.异常的设计原理与 策略处理 java 最佳实践 p93的更多相关文章

  1. Atitit ati licenseService    设计原理

    Atitit ati licenseService    设计原理 C:\0workspace\AtiPlatf\src_atibrow\com\attilax\license\LicenseX.ja ...

  2. Atitit 异常的实现原理 与用户业务异常

    Atitit 异常的实现原理 与用户业务异常 1.1. 异常的实现原理1 1.2. 用户业务异常1 1.3. 异常转译和异常链2 1.4. 避免异常2 1.5. 异常恢复3 1.6. catch代码块 ...

  3. atitit.文件上传带进度条的实现原理and组件选型and最佳实践总结O7

    atitit.文件上传带进度条的实现原理and组件选型and最佳实践总结O7 1. 实现原理 1 2. 大的文件上传原理::使用applet 1 3. 新的bp 2 1. 性能提升---分割小文件上传 ...

  4. Atitit. js mvc 总结(2)----angular 跟 Knockout o99 最佳实践

    Atitit. js mvc 总结(2)----angular  跟 Knockout o99 最佳实践 1. 框架 angular 跟Knockout 1 2. 2. 简单的列表绑定:Knockou ...

  5. 基于ABP落地领域驱动设计-05.实体创建和更新最佳实践

    目录 系列文章 数据传输对象 输入DTO最佳实践 不要在输入DTO中定义不使用的属性 不要重用输入DTO 输入DTO中验证逻辑 输出DTO最佳实践 对象映射 学习帮助 系列文章 基于ABP落地领域驱动 ...

  6. 设计 REST API 的13个最佳实践

    写在前面 之所以翻译这篇文章,是因为自从成为一名前端码农之后,调接口这件事情就成为了家常便饭,并且,还伴随着无数的争论与无奈.编写友好的 restful api 不论对于你的同事,还是将来作为第三方服 ...

  7. Atitit.angular.js 使用最佳实践 原理与常见问题解决与列表显示案例 attilax总结

    Atitit.angular.js 使用最佳实践 原理与常见问题解决与列表显示案例 attilax总结 1. 本文范围 1 2. Angular的优点 1 2.1. 双向数据绑定 1 2.2. dsl ...

  8. Atitit..文件上传组件选型and最佳实践总结(2)----断点续传

    Atitit..文件上传组件选型and最佳实践总结(2)----断点续传 1. 断点续传的原理 1 2. 如何判断一个插件/控件是否支持断点续传?? 1 3. 常用的组件选型结果::马 1 4. 自定 ...

  9. atitit.避免NullPointerException 总结and 最佳实践 o99

    atitit.避免NullPointerException 对于返回集合的方法很简单,只需要返回空的集合就可以了,而不是null. 1 一种可选办法就是不使用空返回值,而是空对象模式: 1 直接抛出e ...

随机推荐

  1. jQuery:validate设置样式

    jquery.validate.js插件里面的样式设置: ... errorClass: "error",validClass: "valid", ... &l ...

  2. http://blog.sina.com.cn/s/blog_546abd9f0101c6au.html

    http://blog.sina.com.cn/s/blog_546abd9f0101c6au.html

  3. Axure 简单原型设计

    简介 Axure RP是一个专业的快速原型设计工具.Axure(发音:Ack-sure),代表美国Axure公司:RP则是Rapid Prototyping(快速原型)的缩写. Axure RP是美国 ...

  4. About stats collected

    pg_class.relpages pg_class.reltuples仅仅是近似值,和实际数据会有点误差: 新建空表.首次insert对自己主动收集和更新统计信息,影响的表pg_class\pg_s ...

  5. WORD中无损复制图片

    问题 默认 Ctrl+C复制出来图片图片的严重模糊,复制出来的不是原图片!因为图片尺寸被修改后复制出来的则是模糊的 解决办法 解决办法把WORD中的图片恢复成默认的,如果对图片进行了缩放请把缩放比恢复 ...

  6. [Objective-C] - NSObject

    Foundation Framework Classes Data Storage:    NSData provides object-oriented storage for arrays of ...

  7. H5 Canvas | 基本操作

    <canvas> - 定义使用 JavaScript 的图像绘制. p.s. ×150. getContext是DOM对象的方法,也就是原生js方法,不能用jQuery对象直接获取 ——— ...

  8. 01-spring-专题IOC

    接口: 1,用于沟通的中介物的抽象化 2,实体把自己提供给外界的一种抽象化说明,用以内部操作分离出外部沟通方法,使其能被修改内部而不影响外界其他实体与其交互的方式(内部可能修改了,但是接口不变). 简 ...

  9. 制作可以 SSH 登录的 Docker 镜像

    Docker使用系列一我们把镜像源改为了阿里云的,方便后续的操作. 执行这个命令就把源地址改为阿里的: curl https://git.oschina.net/feedao/Docker_shell ...

  10. Python-文件修改器

    #-*- coding: utf-8 -*- import os import sys import glob from PyQt4.QtGui import * from PyQt4.QtCore ...