首页 课程 师资 教程 报名

java异常处理机制详解(一)

  • 2019-08-28 11:36:28
  • 2073次 动力节点

  


今天动力节点java学院小编为大家介绍“java异常处理机制详解”,希望对大家有帮助,下面就随小编一起看看java异常处理机制详解吧。


异常机制已经成为判断一门编程语言是否成熟的标准,异常机制可以使程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程序健壮性。


  Java异常机制主要依赖于try、catch、finally、throw、throws五个关键字。


  1、try:它里面放置可能引发异常的代码。


  2、catch:后面对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块,可以有多个catch块。


  3、finally:主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件),异常机制总是保证finally块总是被执行。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者 throw等终止方法的语句,则就不会跳回执行,直接停止。


  4、throw:用于抛出一个实际的异常,可以单独作为语句使用,抛出一个具体的异常对象。


  5、throws:用在方法签名中,用于声明该方法可能抛出的异常。


  Java的异常分为两种,checked异常(编译时异常)和Runtime异常(运行时异常)


  1、 java认为checked异常都是可以再编译阶段被处理的异常,所以它强制程序处理所有的checked异常,而Runtime异常无须处理,java程序必须显式处理checked异常,如果程序没有处理,则在编译时会发生错误,无法通过编译。


  2、 checked异常体现了java设计哲学:没有完善处理的代码根本不会被执行,体现了java的严谨性。


  对于构造大型、健壮、可维护的应用系统而言,错误处理是整个应用需要考虑的重要方面。Java异常处理机制,在程序运行出现意外时,系统会生成一个Exception对象,来通知程序,从而实现将“业务功能实现代码”和“错误处理代码”分离,提供更好的可读性。


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


  不同的catch块,视为了针对不同的异常类,提供不同的处理方法。


  对于错误处理机制,主要有如下的两个缺点:


  1、无法穷举所有异常情况:因为人类的知识是有限的,异常情况总比可以考虑到的情况多,总有漏网之鱼。


  2、错误处理代码和业务实现代码混杂严重影响程序的可读性,会增加程序维护的难度。


  使用try...catch捕获异常


  java提出了一种假设,如果程序可以顺利完成,那么一切正常,把系统的业务实现代码放在try块中定义,所有的异常处理逻辑放在catch块中进行处理。


  即:


     try{

  //业务实现代码

  ...

  }

  catch(Exception e){

  输入不合法

  }


  上面的格式中try块和catch块后的{...}都是不可以省略的!


  执行步骤:


  1、如果执行try块中的业务逻辑代码时出现异常,系统自动生成一个异常对象,该异常对象被提交给java运行环境,这个过程称为抛出(throw)异常。


  2、当java运行环境收到异常对象时,会寻找能处理该异常对象的catch块,如果找到合适的cathc块并把该异常对象交给catch块处理,那这个过程称为捕获(catch)异常;如果java运行时环境找不到捕获异常的catch块,则运行时环境终止,jav程序也将退出。


  注意1:不管程序代码块是否处于try块中,甚至包括catch块中代码,只要执行该代码时出现了异常,系统都会自动生成一个异常对象,如果程序没有为这段代码定义任何catch块,java运行环境肯定找不到处理该异常的catch块,程序肯定在此退出。


  注意2:try块后可以有多个catch块,try块后使用多个catch块是为了针对不同异常类提供的不同的异常处理方式。当系统发生不同意外情况时,系统会生成不同的异常对象,java运行时就会根据该异常对象所属的异常类来决定使用哪个catch块来处理该异常。


  注意3:通常情况下,如果try块被执行一次,则try块后只有一个catch块会被执行,绝不可能有多个catch块被执行,除非在循环中使用类continue开始下一次循环,下一次循环又重新运行了try块,这才可能导致多个catch块被执行。


  注意4:进行异常捕获时,一定要记住先捕获小的异常,再捕获大的异常。


Java的异常类,以及他们的继承关系:


1.gif


  java把所有非正常情况分成两种:异常(Exception)和错误(Error),都是继承自Throwable父类。


  Error错误:一般是指虚拟机相关的问题,如系统崩溃,虚拟机出错误等,这种错误无法恢复或不可能捕获,将导致应用程序中断,通常不处理。


  Throwable():Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。


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


  2、Exception:Exception 类及其子类是 Throwable 的一种形式,它指出了合理的应用程序想要捕获的条件。


  (1)SQLException:该异常提供关于数据库访问错误或其他错误的信息。


  (2)RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。


  (3)IOException:此类为异常的通用类,它是由失败的或中断的 I/O 操作生成的。



  异常对象包含的常用方法:


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


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


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


  4、getStackTrace():返回该异常的跟踪栈信息。


  public class TestException

  {

 

  public static void main(String[] args)

  {

 

  try{

  FileInputStream fis=new FileInputStream("a.txt");

  }

   catch(IOException ioe)

  {

   System.out.println(ioe.getMessage());

  ioe.printStackTrace();

   }

  

   }

  

  }


  使用finally回收资源


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


  因为:java的垃圾回收机制不会回收任何的物理资源,垃圾回收机制只回收堆内存中对象所占用的内存。


  问题1:那么在哪边回收这些物理资源呢?


在finally块中,因为如果try块的某条语句引起一场,该语句后的其他语句通常不会被执行,那将导致位于该语句后的资源回收语句得不到执行;如果在catch块里进行资源回收,但catch块完全有可能得不到执行,这也将导致不能及时回收这些物理资源。所以我们不管try块中的代码是否出现异常,也不管哪个catch块会被执行,finally块总会被执行。


  那么:java异常处理的完整语法结构如下:


try

{

     //业务实现逻辑

     ...

}

catch(SubException e)

{

     //异常处理快1

     ...

}

catch(SubException2 e)

{

     //异常处理快2

     ...

}

     ...

finally

{

    //资源回收块

    ...

}


  以上的异常处理语法结构中


  注意点1:只有try块石必须的,也就是说如果没有try块,则不可能有后面的catch块和finally块;


  注意点2:catch块和finally块都是可选的,但catch块和finally块至少出现其中之一,也可以同时出现;


  注意点3:可以有多个catch块,捕获父类异常的catch块必须位于捕获子类异常的后面;


  注意点4:不能只有try块,既没有catch块,也没有finally块;


  注意点5:多个catch块必须位于try块之后,finally块必须位于所有catch块之后。


  import java.io.FileInputStream;

  import java.io.IOException;

  

  public class TestException

  {

  

      

     public static void main(String[] args)

     {

         // TODO Auto-generated method stub

         FileInputStream fis = null;

         try

         {

            fis = new FileInputStream("a.txt");

         } catch (IOException ioe)

         {

             System.out.println(ioe.getMessage());

            // return语句强制方法返回

             return;

             // 使用exit来退出虚拟机

             // System.exit(1);

         } finally

         {

             // 关闭磁盘文件,回收资源

             if (fis != null)

             {

                try

                {

                     fis.close();

                } catch (IOException ioe)

                 {

                     ioe.printStackTrace();

                 }

             }

            System.out.println("程序已经执行了finally里德资源回收");

         }

     }

 

 }


  运行程序结果:


  a.txt (系统找不到指定的文件。)


  程序已经执行了finally里德资源回收


  如果将catch块中的最后两句注释放入程序,那么结果为:a.txt (系统找不到指定的文件。)


  以上两种情况显示:除非在try块或者catch块中调用了退出虚拟机的方法(即System.exit(1);),否则不管在try块、catch块中执行怎样的代码,出现怎样的情况,异常处理的finally块总是会被执行的。不过,一般情况下,不要再finally块中使用renturn或throw等导致方法终止的语句,因为一旦使用,将会导致try块、catch块中的return、throw语句失效。


public class TestException1

 {

 

      public static boolean test()

      {

          try

          {

              return true;

          } finally

         {

             return false;

         }

     }

 

     public static void main(String[] args)

     {

         boolean a = test();

         System.out.println(a);

     }


 }

  


运行结果:false


  以上的小程序说明:在finally块中定义了一个renturn false语句,这将导致try块中的return true 失去作用!


  总结一下这个小问题:


  当程序执行try块,catch块时遇到return语句或者throw语句,这两个语句都会导致该方法立即结束,所以系统并不会立即执行这两个语句,而是去寻找该异常处理流程中的finally块,如果没有finally块,程序立即执行return语句或者throw语句,方法终止。如果有finally块,系统立即开始执行finally块,只有当finally块执行完成后,系统才会再次跳回来执行try块、catch块里的return或throw语句,如果finally块里也使用了return或throw等导致方法终止的语句,则finally块已经终止了方法,不用再跳回去执行try块、catch块里的任何代码了。


  综上:尽量避免在finally块里使用return或throw等导致方法终止的语句,否则可能出现一些很奇怪的情况!


  异常处理的嵌套


  例如catch块中再次包含了一个完整的异常处理流程,这种在try块,catch块或finally块中包含完整的异常处理流程的情形称为异常处理的嵌套。异常处理流程的代码可以放在任何可执行代码的地方,因此完整的异常处理流程既可放在try块,也可放在catch块,也可放在finally块里。


  嵌套的深度没有很明确的限制,通常没有必要写层次太深的嵌套异常处理,会导致程序可读性降低。


由于java异常处理机制详解的内容太多,本文已满,请看下文:http://www.bjpowernode.com/javazixun/1655.html



选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交