Java语言的异常处理机制研究

来源:互联网 发布:linux配置ftp服务器 编辑:程序博客网 时间:2024/06/14 20:31

Java语言的异常处理机制研究


 
    摘  要 异常是用来处理程序错误的有效机制。本文通过对Java语言异常处理机制的分析,结合实例,对这一处理程序错误的有效方式和设计原则进行了探讨。
    关键词 Java;异常;异常处理机制
 

1 引言

    程序执行时经常会出现除零溢出、数组越界等运行错误,影响程序的正常执行。错误及异常是不可避免的,一个好的应用程序,在满足用户要求的各种功能的同时,还应具备能预见程序执行过程中可能产生的各种异常的能力,并能为异常情况给予恰当处理。在Java语言中,这种技术就是异常处理(Exception Handling)。
    Java语言通过面向对象的异常处理机制来解决运行期间的错误,可以预防错误的程序代码或系统错误所造成的不可预期的结果发生。减少编程人员的工作,增加了程序的灵活性,增加程序的可读性和健壮性[1]
    本文结合实例,对Java语言中的异常处理机制及异常设计原则进行了探讨。

2 Java的异常处理机制

    Java通过面向对象的方法来处理异常。把各种异常进行分类,并提供了良好的接口。在一个方法的运行过程中,如果发生了异常,则这个方法生成代表该异常的一个对象,并把它交给运行时系统。运行时系统寻找相应的代码来处理这一异常。

2.1 Java中的异常类

    面向对象的Java语言把异常封装到类里。Java异常类层次结构如图1所示。Java异常是对象或类的实例,所有异常类的基类是Throwable类。Java将异常分为Error和Exception两大类。Error类描述了Java运行系统中的内部错误、死循环或内存溢出等类似情况,称之为致命性错误。只能在编程阶段解决,运行时程序本身无法解决。只能靠其它程序干预,所以应用程序不应该抛出这类异常[2]。程序设计中关注的是Exception类。它有三个子类,RuntimeException、IOException和其它异常子类,包括用户自定义异常。

    RuntimeException类型的异常是由编程导致的错误,和Error一样,如果在程序运行时产生,只能找出程序中的错误加以修改。Exception的其它子类必须在程序中进行处理,否则不能通过编译。本文研究的正是这类异常。

2.2 Java异常处理方法

    Java程序设计中,采用try……catch……finally语句结构和主动抛出异常语句throw等方法来实现。通过try……catch……finally语句可以捕获一个或多个异常,其基本格式是:
    try{
        语句体
    }catch(异常错误类型变量名){
        语句体
    }finally{
        语句体
    }
    上面语句中的异常对象是在Java运行时由系统抛出的。还可以使用throw语句明确抛出一个异常,其基本格式是:
    throw异常对象
2.2.1 创建和捕获异常
    对异常进行处理时,将引起异常的语句添加到最近的try语句中,由catch进行识别和处理。如果异常发生时能确保有一段代码被执行,则应该使用finally子句。请参看例1。
    例1  class MyEx01{
public int divide(int x,int y)     {
         return x/y;
    }
}
class ExTest01{
    public static void main(String[] args)  {
           try              {
             int result=new MyEx01().divide(3,0);
             System.out.println("result="+result);
           }
           catch(Exception e)            {
                    System.out.println("发生异常,异常类型为:"+e.getMessage());
           }
           finally{
                    System.out.println(“finally语句被执行”);
    }
}
    例1主动产生一个被0除的异常,然后用catch语句捕获。被0除异常是一种ArithmeticException类的异常,通过getMessage()方法显示出具体类型,而finally语句最终也被执行。
2.2.2 自定义异常及抛出异常
    在Java编程的过程中,可以抛出类库中的异常或自定义的异常。Java程序在运行时如果引发了一个可识别的错误,就会产生一个与该错误相对应的异常,这个过程被称为异常的抛出。根据异常类的不同,抛出异常的方法也不同。
    1)系统自动抛出的异常
    所有的系统定义的运行异常都是由系统自动抛出。如例1,由于错误地以0为除数,运行过程中将引发ArithmeticException;这个异常类是系统预先定义好的类,对应于系统可识别的错误,所以Java虚拟机遇到这种错误就会自动中止程序的流程,并新建一个ArithmeticException类的异常,即抛出一个算术运算异常。此程序没有编译错误,但存在运行错误,由于没有接收异常和处理异常的语句,所以程序在运行时给出如此信息。
    2)语句抛出的异常
    用户程序自定义的异常不可能依靠系统自动抛出,而必须借助于throw语句来定义何种情况下产生了这种错误对应的异常,并及时抛出这个异常类的新对象。请参看例2。
    例2  class MyEx02 extends Exception
{
    public MyEx02()
    {
           super("字符串太短");
    }
    public void someMethod(String s) throws MyEx02
    {
      if(s.length()<=3)
      {
     throw new MyEx02();
      }
      else
      {
       System.out.println("字符串长度符合规定");
      }
    }
}      
class ExTest02
{
    public static void main(String[] args)
    {
           try
        {
                    MyEx my=new MyEx02();
                    my.someMethod("abcedef");
                    my.someMethod("ab");
           }
           catch (MyEx02 e)
           {
                    System.out.println(e.getMessage());
           }
    }
}                
    例2这种抛出异常的语句应该被定义在满足一定条件时执行,所以通常把throw语句放在if语句中,即用户定义的逻辑错误发生时才执行。
2.2.3 隐瞒异常,或改报其他异常
    在方法调用过程中有时为了安全保密,内部人员按照一定的约定,然后通过throw语句根据相应情况,灵活主动地抛出异常,可以隐瞒异常,或改报其他异常,请参看例3。
    例3  class MyEx03{
public void testL(String s)throws Exception{
try{
    int i=s.length();
    }catch(NullPointerException e){
    throw new ArraylndexOutOfBoundsException("越界");
    }
    }
public static void main(String[]args){
    MyEx03 exTest=new MyEx03();
    String s=null;
    try{
    exTest.testL(s);
    }catch(Exception e){
    e.printStackTrace();
    }
}
}

3 异常处理的设计原则

3.1 定义分层次的异常

    一般来说,不同的异常需通过定义不同的类来实现,且在产生异常实例中需要用不同的初始化参数。一个好的异常设计需要定义一系列可能的异常树。异常是多种多样的,我们应该尽可能地捕捉到所有的异常,但是将try块的范围扩大并不是一个好的解决方案,相反地,我们应该尽可能地缩小try块的范围,使异常处理与方法的主要逻辑分离,这将有利于代码的调试和维护。

3.2 合理地运用异常父类

    运用异常的基类可以捕获一类异常,可以使程序简捷一些,而且很多时候我们也的确不需要对捕捉的异常类型做特殊的处理,但是也并不是鼓励全都使用父类,比如Exception可以捕捉所有的异常,但如果全都使用Exception的话,对调试和代码维护都是极为不利的。

3.3 每个独立的线程要捕获所有异常和错误

    线程一旦启动,就相当于一个主程序。它的840 方法中如果出现异常或错误,将不会有其它主程序来捕获它。一般在写程序时,会捕获线程中的异常,不捕获将通不过编译,但要记住同时需捕获Error或RuntimeException,否则如果一个线程运行中出现这样的问题,很有可能程序会无声无息地死去。所以一个线程的840 方法中最好要有一个包含整个方法的try……catch块[3]

4 结束语

    计算机语言的演变允许开发人员处理失败,Java对异常处理程序的支持简化了这一任务[4]
本文通过实例分析了Java语言中的异常处理机制,对于采用面向对象的方法进行异常处理,合理优化程序设计,提高系统安全性和稳定性的机制作了初探。

原创粉丝点击