第一段:Java异常的基础知识
第二段:Java异常类类图
下面是这几个类的层次图: java.lang.Object java.lang.Throwable java.lang.Exception java.lang.RuntimeException java.lang.Error java.lang.ThreadDeath
下面四个类的介绍来自java api 文档.
①.、Throwable Throwable 类是 Java 语言中所有错误或异常的超类.只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出.类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型. 两个子类的实例,Error 和 Exception,通常用于指示发生了异常情况.通常,这些实例是在异常情况的上下文中新近创建的,所以呢包含了相关的信息(比如堆栈跟踪数据).
好了,全部的对有关异常API的一个简单介绍,用法都很简单,关键在于理解异常处理的原理,具体用法参看Java API文档.
第三段:Java异常处理机制
对于可能出现异常的代码,有两种处理办法: 第第一段:在方法中用try...catch语句捕获并处理异常,catach语句可以有多个,用来匹配多个异常.例如: public void p(int x){ try{ ... }catch(Exception e){ ... }finally{ ... } }
第第二段:对于处理不了的异常或者要转型的异常,在方法的声明处通过throws语句抛出异常.例如: public void test1() throws MyException{ ... if(....){ throw new MyException(); } } 如果每个方法都是简单的抛出异常,那么在方法调用方法的多层嵌套调用中,Java虚拟机会从出现异常的方法代码块中往回找,直到找到处理该异常的代码块为止.然后将异常交给相应的catch语句处理.如果Java虚拟机追溯到方法调用栈最底部main()方法时,如果仍然没有找到处理异常的代码块,将按照下面的步骤处理: 第第一段:调用异常的对象的printStackTrace()方法,打印方法调用栈的异常信息. 第第二段:如果出现异常的线程为主线程,则整个程序运行终止;如果非主线程,则终止该线程,其他线程继续运行. 通过分析思考可以看出,越早处理异常消耗的资源和时间越小,产生影响的范围也越小.所以呢,不要把自己能处理的异常也抛给调用者. 还有一点,不可忽视:finally语句在任何情况下都必须执行的代码,这样可以保证一些在任何情况下都必须执行代码的可靠性.比如,在数据库查询异常的时候,应该释放JDBC连接等等.finally语句先于return语句执行,而不论其先后位置,也不管是否try块出现异常.finally语句唯一不被执行的情况是方法执行了System.exit()方法.System.exit()的作用是终止当前正在运行的 Java 虚拟机.finally语句块中不能通过给变量赋新值来改变return的返回值,也建议不要在finally块中使用return语句,没有意义还容易导致错误.
最后还应该注意一下异常处理的语法规则: 第第一段:try语句不能单独存在,可以和catch、finally组成 try...catch...finally、try...catch、try...finally三种结构,catch语句可以有一个或多个,finally语句最多一个,try、catch、finally这三个关键字均不能单独使用. 第第二段:try、catch、finally三个代码块中变量的作用域分别独立而不能相互访问.如果要在三个块中都可以访问,则需要将变量定义到这些块的外面. 第第三段:多个catch块时候,Java虚拟机会匹配其中一个异常类或其子类,就执行这个catch块,而不会再执行别的catch块. 第第四段:throw语句后不允许有紧跟其他语句,因为这些没有机会执行. 第第五段:如果一个方法调用了另外一个声明抛出异常的方法,那么这个方法要么处理异常,要么声明抛出.
那怎么判断一个方法可能会出现异常呢?一般来说,方法声明的时候用了throws语句,方法中有throw语句,方法调用的方法声明有throws关键字.
第四段:如何定义和使用异常类
①.、使用已有的异常类,假如为IOException、SQLException. try{ 程序代码 }catch(IOException ioe){ 程序代码 }catch(SQLException sqle){ 程序代码 }finally{ 程序代码 }
这段代码实际上捕获了异常,然后又和盘托出,没有一点意义,如果这样还有什么好处理的,不处理就行了,直接在方法前用throws声明抛出不就得了.异常的捕获就要做一些有意义的处理.
第五段:运行时异常和受检查异常
运行结果:
Hello World!!! 除数为0! 除数为零后程序没有终止啊,呵呵!!!
第六段:异常转型和异常链 异常转型在上面已经提到过了,实际上就是捕获到异常后,将异常以新的类型的异常再抛出,这样做一般为了异常的信息更直观!比如: public void run() throws MyException{ ... try{ ... }catch(IOException e){ ... throw new MyException(); }finally{ ... } }
通过Throwable的两个构造方法可以创建自定义的包含异常原因的异常类型: Throwable(String message, Throwable cause) 构造一个带指定详细消息和 cause 的新 throwable. Throwable(Throwable cause) 构造一个带指定 cause 和 (cause==null ? null :cause.toString())(它通常包含类和 cause 的详细消息)的详细消息的新 throwable. getCause() 返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null. initCause(Throwable cause) 将此 throwable 的 cause 初始化为指定值. 在Throwable的子类Exception中,也有类似的指定异常原因的构造方法: Exception(String message, Throwable cause) 构造带指定详细消息和原因的新异常. Exception(Throwable cause) 根据指定的原因和 (cause==null ? null : cause.toString()) 的详细消息构造新异常(它通常包含 cause 的类和详细消息). 所以呢,可以通过扩展Exception类来构造带有异常原因的新的异常类.
第七段:Java异常处理的原则和技巧
检查日志文件,你就能看到满屏重复的异常.
所以呢,异常只能被打印一次.在哪儿打异常最好呢?.
原则就是自定义异常在抛出前打印一下,其他各层对自定义异常不作任何打印.甚至不用Catch.
对于上面WebServiceClient.login,在这打印是对的,还可以加上自己的一些log信息,如log.fatal("cannotlogintheXXXsystem");至于在其他层,就不在需要打印,处理这个异常了.这样的异常处理没有什么技术含量,只是个异常处理原则,如果人人都遵循(看到自定义不处理,抛自定义异常前处理)这个原则,就能避免重复打印异常日志
再考虑如何把友好的异常信息给终端用户呢,所谓友好,不能总是提示"系统错误,请稍后再试",因为这样能让使用者对系统没有信心.好比领导交给你的任务,你没有完成,你总不能每次都说"这是我的问题,以后改正"吧.对异常进行稍微详细的说明,是必要的.另外,也不能总是把异常的stacktrace原封不动的现实给使用者,如java.io.IOExcepiton:Filecannotbefound.这样会被认为你的程序质量不够高.
可以通过异常指定类型来在Web层解释并转化为友好的异常
.如上列子,可以如下定义MyApplicationExceptoin
如下代码:
异常处理是Java开发中的一个重要部分.
它是关乎每个应用的一个非功能性需求,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等.
Java提供了几个异常处理特性,以try,catch和finally关键字的形式内建于语言自身之中.
Java编程语言也允许你创建新的异常,并通过使用throw和throws关键字抛出它们.
事实上,在Java编程中,Java的异常处理不单单是知道语法这么简单,它必须遵循标准的JDK库,和几个处理错误和异常的开源代码.
这里北大青鸟将讨论一些关于异常处理的Java最佳实践.
①.、为可恢复的错误使用检查型异常,为编程错误使用非检查型错误.
选择检查型还是非检查型异常,对于Java编程人员来说,总是让人感到困惑.
检查型异常保证你对错误条件提供异常处理代码,这是一种从语言到强制你编写健壮的代码的一种方式,但同时会引入大量杂乱的代码并导致其不可读.
当然,如果你有替代品和恢复策略的话,捕捉异常并做些什么看起来似乎也在理.
在Java编程中选择检查型异常还是运行时异常.
在finally块中关闭资源,在正常和异常执行的情况下,保证之前和稀缺资源的合理释放,这由finally块保证.
尽管如此,我们仍然要记住在finally块中关闭资源,这是对于释放像FileDescriptors这类,应用在socket和文件编程的情况下的有限资源很重要的.
日志记录和打印根异常就变得非常重要.
Java异常类提供了getCause方法来检索导致异常的原因,这些(原因)可以对异常的根层次的原因提供更多的信息.
该Java实践对在进行调试或排除故障大有帮助.
时刻记住,如果你将一个异常包装成另一种异常时,构造一个新异常要传递源异常.
这里始终提供精确的真实的信息.
只要你不过度使用检查型异常,你可以最大限度的减少这类情况,这样做的结果是你会得到更清洁的代码.
这是Java最佳实践带来的好处,特定的异常限制到特定的模块,像SQLException放到DAO层,将意思明确的运行时异常抛到客户层.
假如你有方法从ResultSet(结果集)中进行读取,这时常会抛出SQLException异常而不会移到下一元素,这将会比不抛出异常的正常代码执行的慢的多.
所以呢最大限度的减少不必要的异常捕捉和移动,那里没有什么固定的原因.
不要仅仅是抛出和捕捉异常,如果你能使用boolean变量去表示执行结果,可能会得到更整洁,更高性能的解决方案.
修正错误的根源,避免不必须要的异常捕捉.
作为一个java 程序员,特别是刚入门或初学者,遇到的最多的异常我想当属 java.lang.NullPointerException,当然这是一个不可避免的.不管你是多老的程序员,写的程序也不能保证不出现这个异常.但不可杜绝,并不代表不可避免,不可减少其出现的概率.下面就探讨下如何尽量避免其出现,首先看常见的出现该异常的原因. 常见原因至少有以下几类: 对java 对象不熟悉,特别体现在初学者及刚入门身上.如:类的成员还是对象的时候,初学者往往不知道如何初始化成员对象,结果导致对象为初始化就调用. 数据是从外部获取,如数据库,取出数据后不检查就直接调用,常发生在用hibernate 等orm 工具取完数据后数据展示部分. java代码编写习惯.编写类方法不对方法参数进行检查就使用. 引入外部包,而没有引入外部包依赖包 粗心.这是最大的原因,特别是对于有一定编程经验的人来说
解决方法: 第一类属于java 基础不牢,建议多做练习,熟悉java 对象生命周期的相关知识.如java 对象内存分配,堆与栈,java 初始化过程等. 在外部读入数据的话,建议在读入数据后就检查其是否为null .当然有时候也跟需求来定,但使用前必须做好检查工作. 跟编程经验有相当关系.公用的方法,一般使用前检查参数,该抛出异常的抛出异常,该用默认值的用默认值处理.一些私有方法,人们因为觉得只有自己使用,自己控制不传人null 值就可以,懒得去检查空异常.确实我自己也常这样干,但发现自己写的,但自己却总保证不了,不传入空.所以建议使用前检查,但可以不抛出异常,可使用断言,自己用默认值处理掉. 引入外部包出现NullPointerException,随着各种框架的发展而越来越常见.主要是人们盲目引用各种包,而不去详细评估引用包的效果,及不去了解所引入包的依赖包.现在有maven 工具,如果使用它构建工程的话,依赖报错可能就会少点了. 粗心.这个就没办法了,相信没几个人改得了.且因为粗心而出现的bug,自己往往很难找出原因,这时可以借下团队的力量,让同事帮你去找,可能很快就找到了 如何找NullPointerException 出错代码: NullPointerException 异常很找出出错位置还是比较容易的,java 的异常链机制可以让你很快找到错误代码所在.这里提醒一点千万不要使用 try { 代码; }catch(Exception){} 因为这样出错了控制台不报,log 不记,找死你.
以上就是土嘎嘎小编大虾米为大家整理的相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!