`
海鹤
  • 浏览: 919 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

异常处理

阅读更多
首先,java的异常是什么?抛去官方冗长的定义,我觉得异常或者说exception,其实可以理解为这样一句话:“wow!!这可不是我期待的状态”。


如果这样理解异常,那么对于何时使用异常也就再清楚不过了。那就是,只有当出现了不在正常流程之中的某种状态,这个时候就应该使用异常了。比如连接超时、传入的参数为null或者数据无法插入到数据库。


那么,为什么我们要使用异常呢?理由其实很简单,为了更加简洁的代码或者说为了OO。如果java没有异常,我们会怎么处理呢?
if(aMethod() == -1 )
{
//do someting
}
else
{
//do someting
}
有了异常以后,我们怎么做呢?
try
{
aMethod();
}catch(MyException e){
//do someting
}
或者
public anotherMethod() throws MyException
{
aMethod();
}
这里只列举了一个最简单的例子。如果aMethod()这个方法到处都需要调用,这种好处就会更显著了。


至于我们需要不需要使用异常呢?答案必然是肯定的。但是网上也有一些声音说,异常是一种耗费性能的操作,应该少使或者尽量不使。我认为,这跟没有很好的理解如何使用异常有关系。


下面我就来说说,最重要的一点,也就是how,如何使用异常。


首先,我们来看看,当发生异常的时候,JVM做了什么?



为了抛出异常,JVM 发出 athrow 字节码指令。 athrow 指令引起 JVM 将异常对象弹出执行堆栈。然后 JVM 搜索当前执行堆栈帧来寻找第一个 catch 子句,这个子句可以处理该类的一个异常或者其超类的一个异常。如果在当前的堆栈帧里没有找到 catch block ,那么当前堆栈帧就被释放,异常在下一个堆栈帧的上下文中被重新抛出,如此这般,直到找到包含匹配的 catch 子句的堆栈帧,或者是到了执行堆栈的底部。最后,如果没找到适当的 catch 块,所有的堆栈帧都会被释放,线程在 ThreadGroup 对象有了处理异常的机会后被终止(参考 ThreadGroup.uncaughtException )。如果找到了适当的 catch 块,程序计数器会重置到那一

块代码的第一行。 (注:1)



从上面的描述可以看出,抛出异常是一种代价很高的操作。有的人可能要问了,如果只是为了简洁的代码或者OO,这种代价值得吗?我的回答是,不值得!!!这点和我上面说的并不冲突。如果有一点经济学的知识,一定会知道边际量这个概念,说白了就是我多花一个单位的成本,是否可以带过我多于一单位的收益。将这点用到编程上也是通用的。
我们可以考虑这样一段代码
for(int i=0;i<list.size();i++)
{
AClass myClass = list.get(i);
if(myClass.aValue!=null && !"".equals(myClass.aValue))
{
//do something
}
}


这段代码很好的处理了参数不正常的情况。但有一个问题,每次循环程序都需要判断参数是否正常。假设我们知道大部分的参数都是正常的,那么这些操作就显得有些浪费了。如果改成
for(int i=0;i<list.size();i++)
{
AClass myClass = list.get(i);
try
{
//do something
}catch(Exception e){}
}
这样只有当很小几率发生错误的时候,我们就可以节省一些操作。这也就是经济学上说的边际收益大于边际成本的时候,只有这个状态,我们才应该这样使。反观另外一个状态,如果我们不能确定参数是否大部分为正常或者我们确定大部分参数都不会为正常,那么就应该使用第一种方法。总之,这点是需要灵活掌握的。


另外一个值得注意的地方就是,不要将异常用于流程跳转,异常就是指异常的状态,而不是控制语句。如果你能注意这点,你就已经避免了90%的错误异常应用。举个例子。inputStream#read大家一定都用过,为什么read方法要返回-1作为读取到文件尾的状态,而不是用异常,就是这个道理。



关于如何使用异常的另外一点就是,我们如何catch异常。这一点其实也很简单,总结为一句话就是,如果你不知道如何处理这个异常,那么就不要catch这个异常。


我们经常会遇见这样一种情景:我们调用了某个接口,这个接口抛出了一个checkedexception。这个时候就是考验你的时候了,catch还是throw 这是个问题。我的经验是,如果你觉得这个异常是一个可恢复的异常,比如参数错误,那么你就需要catch这个

exception,然后告诉用户重新输入。如果这个exception是一个不可恢复的exception,比如SQLException,那么你干脆就不要处理它,把它留给底层去处理,让底层定向到统一的异常页面。当然,这种操作并不是严格的,你也可以catch这个exception,然后返回到你自己的异常页面。


最值得注意的是,永远不要没有理由的私吞exception。比如
try
{



}catch(Exception e){
//do nothing
}
如果你确定可以这种做,那么没有关系。但是如果你不能,千万一定不要这么做,如果你这么做了,很有可能导致无法定位异常,把自己或者别人搞到死。



关于如何使用异常的最后一个问题就是runtimeexception 或者 checkedexception,这是个问题!


很长一段时间,我也曾困惑于这个问题,记得以前看过一本书,好像是java夜未眠,记不清楚了。里面说,要尽量使用runtimexception,但是当我这样做的时候,问题就来了,调用我接口的人不知道我的方法会抛出什么异常,也就无从处理了,这样就导致了程序的不健壮。其实这个问题需要根据你的业务进行判断,没有什么尽量或者最好。一个简单的原则是如果希望客户程序员有意识地采取措施,那么抛出checkedexception.举两个例子
public void aMethod(String s)
{
if(s==null) throw new Runtimeexception();
}
public void otherMethod(String uri) throws NoSuchFileException
{
try
{
File file = new File(uri)
}catch(IOException e)
{
throw new NoSuchFileException()
}
}


看出点什么了吗?你肯定很奇怪为什么都是参数不正确,第一个方法抛出的是一个RuntimeException而第二个是一个CheckedException。因为s为null是一个我们非期待的参数,而这种状态可能并不是经常出现的,属于一种非业务错误或者不可恢复异常,我们不需要明确的通知客户程序员。



而第二个不同,第二个异常代表用户输入了某种错误的参数,而这个异常需要客户程序员去通知用户。所以要求客户程序员去catch这样exception。


以上是我对异常的一些理解,如果大家有不同意见可以进行讨论


参考资料
1.关注性能: 异常的异常:http://www-128.ibm.com/developerworks/cn/java/j-perf02104/index.html
2.异常设计----何使用异常的原则 http://www.cnblogs.com/javaVillage/articles/384483.html
1
2
分享到:
评论

相关推荐

    C#异常处理总结及简单实例

    C#异常处理总结及简单实例 一、异常处理的理解? 异常处理是指程序在运行过程中,发生错误会导致程序退出,这种错误,就叫做异常。 因此处理这种错误,就称为异常处理。 二、异常处理如何操作? C# 异常处理时建立在...

    MySQL定义异常和异常处理详解

    MySQL中的异常处理是数据库编程中不可或缺的一部分,它允许开发者预设对可能出现的错误或异常的响应,从而确保程序的稳定性和健壮性。在MySQL中,异常定义和处理主要是通过`DECLARE`语句来实现的。 1. **异常定义**...

    异常处理 异常处理 异常处理

    异常处理是编程中的一种机制,用于捕获和处理运行时发生的错误或异常情况。异常可以由硬件引发,如硬件异常,也可以由操作系统或应用程序自身触发,即软件异常。当异常发生时,操作系统允许程序有机会检查异常类型并...

    易语言线程结构异常处理

    在易语言中,线程是并发执行的程序单位,线程结构异常处理是编程过程中非常重要的一环,因为线程可能会遇到各种异常情况,如内存访问错误、除零异常等。 线程结构异常处理源码是易语言中处理这些异常的关键部分。当...

    java异常处理习题

    Java 异常处理习题 Java 异常处理是 Java 编程语言中的一种重要机制,用于处理程序在运行时可能出现的错误或异常情况。下面是关于 Java 异常处理的习题和知识点总结: 一、Java 异常处理关键字 * Java 中用来抛出...

    易语言HOOK异常处理

    "New_SE_Handler"可能是一个新的结构化异常处理程序,结构化异常处理(SEH)是Windows操作系统中的一个特性,用于处理硬件和软件异常。 "GetSeAddr"可能是获取异常发生时的地址函数,这对于分析异常原因和定位问题...

    c/vc++/MFC异常处理/结构化异常处理 浅析

    在编程领域,异常处理是确保程序健壮性与稳定性的关键技术。对于C、C++以及基于MFC(Microsoft Foundation Classes)的开发来说,异常处理更是不可或缺的一部分。本篇文章将深入浅析C、C++中的异常处理机制以及MFC中...

    详解SpringCloud Finchley Gateway 统一异常处理

    详解 SpringCloud Finchley Gateway 统一异常处理 SpringCloud Finchley Gateway 统一异常处理是指在使用 SpringCloud Finchley 版本的 Gateway 时,如何统一处理系统级异常的方法。默认情况下,SpringCloud ...

    异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt

    【异常处理】是编程中必不可少的一个环节,尤其是在Java这样的面向对象语言中。异常处理机制使得程序在遇到错误时能够优雅地中断执行流程,提供错误信息,并有机会进行恢复操作,而不是简单地崩溃。以下是对异常处理...

    异常处理机制知识点小总结

    异常处理是Java编程中至关重要的一个概念,它确保了程序在遇到错误或异常情况时能够以优雅的方式继续执行或者终止。下面是对Java异常处理机制的详细解析。 在Java中,异常是程序运行时发生的错误,它中断了正常的...

    ARM处理器异常处理步骤

    ARM处理器异常处理是指ARM微处理器对各种异常情况作出响应和处理的过程。异常指的是处理器在正常执行程序时遇到的特殊情况,例如外部中断请求、未对齐的内存访问错误、指令预取终止等。为了保证系统的稳定性和正确性...

    Power builder9异常处理

    在 PowerBuilder 9(简称 PB9)开发过程中,异常处理是一项关键的技术,它能帮助开发者有效地管理和解决程序中出现的错误,确保系统的稳定运行。在实际应用中,开发者经常会遇到各种预知和不可预知的问题,如系统级...

    游标和异常处理 游标和异常处理

    游标和异常处理 游标是 SQL 的一个内存工作区,由系统或用户以变量的形式定义。游标的作用就是用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将...

    ADS异常处理.pptADS异常处理.pptADS异常处理.ppt

    《ADS异常处理详解》 异常处理是嵌入式系统中至关重要的部分,特别是在基于ARM架构的系统中。本文将深入探讨ARM处理器的异常处理机制,包括异常类型、处理流程、异常优先级以及向量表等内容。 一、异常类型 ARM...

    java实验报告4-异常处理

    Java异常处理是编程中至关重要的一个环节,它确保了程序在遇到错误时能够优雅地运行,而不是突然崩溃。本实验报告“java实验报告4-异常处理”旨在帮助初学者掌握Java中的异常处理机制,以及如何利用log4j进行日志...

    reactnative异常处理库

    React Native 异常处理库是专门为在React Native框架下开发的混合移动应用提供错误管理和调试支持的工具。React Native允许开发者使用JavaScript编写原生移动应用,但JavaScript代码的运行环境中可能会遇到各种错误...

    Spring Cloud Gateway的全局异常处理

    ### Spring Cloud Gateway全局异常处理详解 #### 一、引言 在微服务架构中,网关作为服务入口,承担着路由转发、限流熔断、鉴权认证等职责。Spring Cloud Gateway作为一款基于Spring Framework 5、Project Reactor...

    两数计算+异常处理

    课程作业,实现两数计算及其异常处理,异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。 Java中的异常可以是函数...

Global site tag (gtag.js) - Google Analytics