黑马 程序员——Java基础---异常处理

黑马程序员——Java基础---异常处理

 

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------

 

 一、概述    

  Java异常机制可以使程序中的异常处理代码和正常业务代码分离,保证程序代码更加优雅,并可以提高程序的健壮性。当程序运行中出现意外情况时,系统会自动生成一个Exception对象来通知程序,从而实现将“业务功能实现代码”和“错误处理代码”分离,提供更好的可读性。

  Java异常机制主要依赖于try、catch、finally、throw和throws五个关键字,并且将异常分为两种,编译(Checked)异常和Runtime异常,编译异常是编译阶段被处理的异常,Runtime异常发生则无须处理,直接结束程序。

 

二、正文

1、异常处理机制

1.1 使用try…catch捕获异常

  Java提供了一种假设:如果程序可以顺利完成,那就“一切正常”,把系统的业务实现代码放在try块中定义,所有的异常处理逻辑放在catch块中进行处理。下面是具体的语法结构:

try{

       //业务实现代码

       ......

}

catch (Exception e){

       alert 输入不合法

       goto retry

}

     如果执行try块里的业务逻辑代码是出现异常,系统自动生成一个异常对象,该对象被提交到java运行时环境,这个过程称为抛出(throw)异常。当java收到该对象,会寻找该异常对象的catch块,如果找到合适catch块,则把该异常交给该catch块处理,这个过程称为捕获(catch)异常。如果java找不到catch块则程序终止退出。

      当java收到异常对象是,该怎么该异常对象寻找catch块呢?具体格式如下:

try{

       //业务实现代码

       ......

}

catch (ClassException1 e1){

       ......

}

catch (ClassException2 e2){

       .......

}

......

      当java接受到异常对象时,会依次判断该异常对象是否是catch中异常类或其子类实例,如果是则调用该catch块,否则再次拿该异常对象和下一个catch块里的异常类进行对比。当程序进入负责处理的catch块中,会根据传入的异常类获取异常信息。

      注意:try块与if不一样,try后面的{}不可以省略,catch也一样,还有try块声明的变量是局部变量,它只在try中有效,在catch中不能访问。

 

1.2 使用finally回收资源

  有些是时候程序在try中打开了一些物理资源(如数据库连接、网络连接和磁盘文件等),这些物理资源都必须显式回收。为了保证一定能回收try块中打开的物理资源,java提供了finally,不论代码是否出现异常,甚至try块或catch块中执行了return语句,finally块总会被执行。具体语法格式如下:

//catch块也可省略

try{

       //业务实现代码

       ......

}

catch (ClassException1 e1){

       ......

}

catch (ClassException2 e2){

       .......

}

......

finally{

       //资源回收块

       ......

}

      注意:除非在try和catch块中调用了退出虚拟机操作,否则finally块不管什么情况都会执行其中代码。尽量避免在finally块中使用return或throw等导致方法终止的语句,否则容易出现一些很奇怪的情况。

 

2Checked异常和Runtime异常

      Java的异常分为两大类:Checked和Runtime异常。所有RuntimeException类及其子类的实例被称为Runtime异常,其他的则被称为Checked异常。如果程序没有显式处理Checked异常,那么该程序无法编译通过。Runtime异常则无须显式声明抛出,如果程序需捕获Runtime异常,可用try…catch块来实现。

 

2.1 使用throws声明抛出异常

      当当前方法不知道如何处理这种类型的异常,则可使用throws声明抛出异常,交给调用者处理,如果处理不了则可在用throws抛出,最终也可以交给虚拟机处理,虚拟机处理方法是打印异常信息,并终止程序。

      Throws声明抛出只能在方法签名中使用,throws可以声明抛出多个异常类,多个异常类之间用逗号隔开。具体语法格式如下:

class ThrowsTest throws Exception1,Exception2......{}

       如果某段代码使用了throws声明的方法,该方法声明抛出了Checked异常,则表明该方法希望他的调用者来处理该异常。

      注意:大部分情况下推荐使用Runtime异常,因为更加简洁。

 

2.2 使用throw抛出异常

      当程序出错时,java允许程序使用throw自行抛出异常。例如饭后出去散步,突然下雨,打破了原定计划,就属于一种异常。使用throw抛出异常,每次只能抛出一个异常实例,具体格式如下: 

throw ExceptionInstance;

下面是一段简单的代码:

class ThrowDemo {

 

static void throwOne() {

 

System.out.println("throwOne.");

//throw在内部抛出异常

throw new IllegalAccessException("demo");

 

}

 

public static void main(String args[]) {

 

throwOne();

 

}

}

       上面程序在编译时无法通过,因为throw抛出了IllegalAccessException异常,该异常属于Checked异常,如果要抛出必须在方法外面用throws声明,即throwOne() throws IllegalAccessException ,那么调用该方法的main函数必须使用try…catch进行捕捉,但是如果该异常是Runtime异常或其子类的话,则可以不必抛出。

      注意:如果throw在内部抛出异常,如果使用了try…catch进行了异常捕捉的话,也可不必用throws在外部声明抛出异常,也就是说如果抛出的异常得到了解决,就可以不使用throws。

 

2.3 自定义异常

      通常情况下,程序在抛出异常时,应该选择合适的异常类,从而明确地描述该异常情况。因此,程序常常需要抛出自定义异常。

      用户自定义异常都应继承Exception基类,如果希望自定义Runtime异常,则应该继承RuntimeException基类。定义异常时通常需要两个构造器:一个是无参数构造器;另一个是带一个字符串参数的构造器,这个字符串将作为该异常对象的描述信息,下面代码建立了一个自定义异常:

public class MyExceptiion extends Exception{

       //无参数的构造器

       public MyExceptiion(){}

       //带一个字符串参数的构造器

       public MyExceptiion(String msg){

              super(msg);

       }

}

  上面程序的msg属于就是该异常的详细描述信息。如果需要定义Runtime异常,只需将上面Exception基类改为RuntimeExcep基类即可。

 

3、异常处理规则

      成功的异常处理应该满足下面4点:

1.使程序代码混乱最小化

2.捕获并保留诊断信息

3.通知合适的人员

4.采用合适的方式结束异常活动。

      不要过度的使用异常。滥用的话会带来一些负面影响。主要表现在:把异常和普通错误混淆在一起,不再编写任何错误处理代码,而是简单的抛出异常来代替所有的错误处理;使用异常处理来代替流程控制。

      不要使用庞大的try块。这样会难免在try块后紧跟大量的catch块才可以这对不同的异常提供不同的处理逻辑,这样反而增加了编程的复杂度。

      不要忽略捕获到的异常。建议对异常采取适当的措施,比如:处理异常,重写抛出异常或在合适的层处理异常。

 

三、总结

  我的这篇博文主要介绍了java异常处理机制的相关知识,比较详细的介绍了try、catch、finally、throw和throws5个关键字的用法,并介绍了Checked和Runtime异常之间的区别,最后讲到了java的异常处理原则,希望这些能对大家有些帮助。

posted @ 2015-03-23 09:53  山顶上的牛  阅读(146)  评论(0编辑  收藏  举报