Java 异常处理

来源:互联网 发布:控制台窗口界面编程 编辑:程序博客网 时间:2024/06/14 08:13

Java把所有的异常情况分为两种异常Exception)和错误(Error),均继承自 Throwable父类。

Error:一般指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这类错误无法恢复或不可能捕获,将导致应用程序中断。通常应用程序无法处理这些错误,因此在应用程序在不应该试图使用catch块来捕获Error对象。也无需在其throws子句中声明该方法可能抛出的Error及其任何子类。

Exception异常又分为两种

Checked异常

java认为Checked异常都是可以被处理(修复)的异常,所以java程序必须显示处理Checked异常。如果程序没有处理Checked异常,该程序在编译时就会发生错误,无法通过编译。可以提醒程序员代码可能存在的问题。

Runtime异常:

所有的RuntimeExecption类及其子类的实例都被称为Runtime异常。其它的则都是Checked异常。Runtime异常不强制要求处理。

异常处理机制:

抛出异常如果执行try块里的业务逻辑代码时出现异常,系统自动生成一个异常对象,该异常对象被提交给java运行环境。

捕获异常:当java运行时环境收到异常对象时,会寻找能处理该异常对象的catch块,如果找到合适的catch块,则把该异常对象交给该catch块处理。如果java运行环境找不到捕获异常的catch块,则运行时环境终止,java程序也将退出。

 

java运行环境接受到异常对象后,会依次判断该异常对象是否是catch块后异常类或者其子类的实例,如果是,java运行时环境将调用该对象和下一个catch块里的异常类进行比较。当程序进入负责处理的catch块时,系统生成的异常对象ex将会传给catch块后的异常形参,从而允许catch块通过该对象来获得异常的详细信息。

 

在通常情况下,如果try块被执行一次,则try块后只有一个catch块会被执行,绝不可能有多个catch块被执行。

 

trycatch块后的花括号是不可以被省略的,try中定义的变量是代码块内局部变量,它只在try块中有效。

 

 

多异常捕获

java 7开始,一个catch块可以捕获多种类型的异常。

使用一个catch块捕获多个异常是需要注意

多个异常类型之间用 |隔开。

②异常变量有隐式final修饰,因此程序不能对异常变量重新赋值。

访问异常信息:

getMessage();返回该异常的详细描述字符串

printStackTrace();将该异常的跟踪栈信息输出到标准错误输出。

printStackTrace(PrintStream s );将该异常的跟踪栈信息输出到指定输出流

getStackTrace();返回该异常的跟踪栈信息

使用finally回收资源

有些时候,程序在try块中打开了一些物理资源(例如数据库连接、网络连接和磁盘文件等),这些物理资源必须显式回收。

Java的垃圾回收机制不会回收任何物理资源,垃圾回收机制只能回收堆内存中对象占用的内存)

 

不管try块中的代码是否出现异常,也不管哪一个catch块被执行,甚至在try块或者catch块中执行了return语句,finally块中的代码总是会被执行(除非在try catch块中调用了退出虚拟机的方法

System.exit();

 

值得注意的是

在通常情况下,不要在finally块中使用如return throw等导致方法终止的语句,一旦在finally块中使用了这些语句,将会导致try块,catch块中的return语句 throw语句失效。

 

Try with resources

java 7开始支持自动关闭资源的try语句  try关键字后紧跟一对圆括号,圆括号可以声明、初始化一个或者多个资源(需要显式关闭的资源)

值得注意的是

为了保证try语句可以正常的关闭资源,这些资源实现类必须实现AutoCloseableCloseable接口,实现这两个接后就必须实现 close方法。

其中CloseableAutoCloseable的子接口Closeable接口中的close方法声明抛出了IOExecption,因此它的实现类在实现close方法时只能声明抛出IOExecption或者其子类,而AutoCloseableclose方法声明抛出的是 Exception,因此它的实现类的close方法可以声明抛出任何异常。

 

try with resources语句相当于包含了隐式的用于关闭资源的finally语句)

 

使用throws声明抛出异常

在当前方法不知道该如何处理这种类型的异常时,该异常应该由上一级调用者处理;如果main方法也不知道如何处理这种类型的异常,也可以使用throws声明抛出异常,将该异常交给jvm处理。jvm对异常的处理方法是,打印异常跟踪栈信息,并终止程序运行。

 

使用throw抛出异常

java允许程序自行抛出异常,使用throw语句来完成。

throw语句可以单独使用,throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例。

系统在处理开发者自行抛出的异常时跟处理系统自动抛出的异常机制一样:中止当前执行流,跳到该异常对应的catch块,由该catch块来处理该异常。

 

java7开始, java编译器会检查throw语句抛出异常的实际类型

自定义异常类

用户自定义的异常类都应该继承自 Exception基类,如果希望自定义Runtime异常,则应该继承RuntimeException基类,定义异常类需要提供两个构造器

①带一个字符串参数的(这个字符串将作为该异常对象的描述信息,也就是getMessage方法的返回值)

②无参数的

 

Catchthrow同时使用

当一个异常出现时,单靠某个方法无法完全处理该异常,必须由几个方法协作才可以完全处理该异常,在这种情况下就需要更加复杂的处理方式

可以在catch块中结合throw语句来实现——在异常出现的当前方法中,程序只对异常部分进行处理,还有些处理需要在方法的调用者中才能完成,所以应该再次抛出异常让该方法的调用者也能捕获异常。

异常链

把原始的异常直接传递给用户是一种不负责任的表现。通常的做法是

程序先捕获原始异常,然后抛出一个新的业务异常,新的业务异常中包含了对用户的提示信息,这种处理方式称为异常转译。

把原始异常信息隐藏起来,仅向上提供必要的异常提示信息的处理方式,可以保证底层异常不会扩散到表现层,可以避免向上暴露太多实现细节。

 

jdk1.4开始,所有的Throwable的子类在构造器中都可以接收一个causeThrowable类型)对象作为参数用于表示原始异常,以实现异常的追踪

 

合理的异常处理规则

①不要过度使用异常

②不要使用过于庞大的try

③避免使用catch all语句

④不要忽略捕获到的异常

原创粉丝点击