首页 课程 师资 教程 报名

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

  • 2019-08-28 11:37:03
  • 2010次 动力节点

  


动力节点java学院小编介绍的“java异常处理机制详解”的内容太长,上文链接请看:http://www.bjpowernode.com/javazixun/1654.html


Checked异常和Runtime异常体系


  java异常被分为两大类:Checked异常和Runtime异常(运行时异常)。


  所有RuntimeException类及其子类的实例被称为Runtime异常,不是RuntimeException类及其子类的异常实例则被称为Checked异常。


  只有java语言提供了Checked异常,其他语言都没有提供,java认为Checked异常都是可以被处理(修复)的异常,所以java程序无须显式的处理Checked异常。如果程序没有处理Checked异常,该程序在编译时就会发生错误,无法通过编译。


  Checked异常的处理方式:


  (1)当方法明确知道如何处理异常,程序应该使用try...catch块来捕获该异常,然后在对应的catch块中修补该异常。


    (2)当方法不知道如何处理异常,应该在定义该方法时声明抛出该异常。


  Runtime异常无须显式声明抛出,如果程序需要捕捉Runtime异常,也可以使用try...catch块来捕获Runtime异常。


  问题是:大部分的方法总是不能明确知道如何处理异常,这就只能声明抛出异常了。


  使用throws抛出异常


  使用throws抛出异常的思路是:当前方法不知道如何处理这种类型的异常,该异常应该由上一级调用者处理,如果main方法也不知道应该如何处理这种类型的异常,也可以使用使用throws声明抛出异常,该异常将交给JVM来处理。


  JVM对异常的处理方法:打印异常跟踪栈的信息,并终止程序运行,所以有很多程序遇到异常后自动结束。


  使用throws抛出异常的格式:


  throws声明的抛出的语法格式紧跟在方法之后,可以声明多个异常类,多个异常类之间以逗号隔开。一旦使用了throws语句声明抛出异常,就不用再使用try...catch来捕获异常了。


  如:throws ExceptionClass1,ExceptionClass2...


  注意点1:如果某段代码调用了一个带throws声明的方法,该方法声明抛出了Checked异常,这表明该方法希望它的调用者来处理该异常。那么这段代码要么放在try块中显示捕获该异常,要么这段代码处于另一个带throws声明抛出的方法中。


  举例如下:


 //方法一:

  

  import java.io.FileInputStream;

  import java.io.IOException;

  

  public class TestException2

  {

  

      // test() 方法抛出了异常,那么test()方法的调用者要么放在try块中显示捕获该异常,要么这段代码处于另一个带throws声明抛出的方法中。

 

     // 以下为后者的处理方法

 

     public static void test() throws IOException

     {

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

     }

 

    public static void main(String[] args) throws Exception

     {

         test();

     }


 }


//方法二:

  

  import java.io.FileInputStream;

  import java.io.IOException;

  

  public class TestException2

  {

  

      public static void test() throws IOException

     {

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

     }

 

     public static void main(String[] args)

     {

         try

         {

             test();

        } catch (IOException e)

         {

             // TODO Auto-generated catch block

             e.printStackTrace();

         }

     }

 

 }

 

使用throws声明抛出异常时有一个限制:就是方法重写时的“两小”中的一条规则:子类方法声明抛出的异常类型应该是父类方法声明抛出的异常类型的子类或或相等,子类方法中不允许比父类方法声明抛出更多异常。即如果子类抛出的异常是父类抛出的异常的父类,那么程序无法通过编译。


  因为Checked异常存在一些不便之处,大部分情况,可以使用Runtime异常,如果程序需要在合适的地方捕获异常,并对异常进行处理,程序一样可以用try...catch捕获Runtime异常。


  使用throw抛出异常


  当程序出现错误时,系统会自动抛出异常,另外,java也允许程序自行抛出异常,自行抛出异常使用throw语句完成!


  抛出异常:


  如果需要在程序中自行抛出异常,应使用throw语句,throw语句可以单独使用,throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例。throw语句的格式如下:throw ExceptionInstance;


  throw语句抛出异常的两种情况:


  1、当throw语句抛出的异常是Checked异常,则该throw语句要么处于try块里显式捕获该异常,要么放在一个带throws声明抛出的方法中,即把异常交给方法的调用者处理。


  2、当throw语句抛出的异常是Runtime异常,则该语句无须放在try块内,也无须放在带throws声明抛出的方法中,程序既可以显式使用try...catch来捕获并处理该异常,也可以完全不理会该异常,把该异常交给方法的调用者处理。


       举例如下:


public class TestException3

 {

  

      public static void throwChecked(int a) throws Exception

      {

          if (a < 0)

          {

             

             throw new Exception("a的值大于0,不符合要求");

         }

     }

 

     public static void throwRuntime(int a)

     {

        if (a < 0)

         {

             

             throw new RuntimeException("a的值大于0,不符合要求");

         } else

        {

             System.out.println("a的值为:" + a);

         }

     }

 

     public static void main(String[] args)

     {

        try

         {

            

             throwChecked(-3);

         } catch (Exception e)

         {

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

         }

         throwRuntime(3);

     }

 

 }


  由上面的代码显式:自行抛出Runtime异常比自行抛出Checked异常的灵活性更好。


  自定义异常类


  用户自定义异常都应该继承Exception基类,如果希望自定义Runtime异常,则应该继承RuntimeException基类。


  应以异常类通常需要提供两种构造器:一个是无参数的构造器,另一个是带一个字符串的构造器,这个字符串将作为该异常对象的详细说明(也就是异常对象的getMessage方法的返回值)。


  通常情况下,程序会很少自行抛出系统异常,因为异常的类名通常包含了该异常的有用信息,所以在选择抛出什么异常时,应该选择合适的异常类,从而可以明确地描述异常情况,这样程序常常需要定义异常类。


  用户定义异常类,需要基础Exception基类,如果希望定义RuntimeException基类,就应该继承该基类,定义异常类时通常需要提供两种构造器:


1、无参的构造器。


2、带字符串的构造器,这个字符串作为该异常对象的详细说明,(也就是异常对象的getMessage方法返回值),调用super将字符串参数传给异常对象的message属性,message属性就是异常对象的详细描述信息。


  例子如下:


 public class TestException4 extends Exception

 {

 

     public TestException4()

      {

 

     }

  

      public TestException4(String msg)

     {

         super(msg);

     }

 

 }


  catch和throw同时使用


  前面已有两种异常处理方法:


  1、在异常出现的方法内捕获并处理,方法的调用者将不能再次捕获该异常。


  2、该方法签名中声明抛出该异常,将该异常完全交给方法调用者处理。


  但是在实际应用中往往需要更复杂的处理方式,即异常出现的当前方法中,程序只对异常进行部分处理,还有些处理需要在该方法的调用者中才能完成,所以应该再次抛出异常,可以让该方法的调用者也能捕获到异常。


  为了实现这种靠多个方法协作处理同一个异常的情形,可以通过catch块中结合throw来完成。


  举例catch和throw同时使用的例子:


 public class TestException4

  {

      // 以下AuctionException这个异常是自定义的异常类

      private double initPrice = 30.0;

  

      public void bid(String bidPrice) throws AuctionException

      {

          double d = 0.0;

         try

         {

             d = Double.parseDouble(bidPrice);

         } catch (Exception e)

         {

             e.printStackTrace();

             throw new AuctionException("竞拍价必须是数值,不能包含其他字符!");

         }

         if (initPrice > d)

         {

             throw new AuctionException("竞拍价比起拍价低,不允许竞拍!");

         }

         initPrice = d;

     }

 

    public static void main(String[] args)

    {

         TestException4 ta = new TestException4();

         try

         {

             ta.bid("df");

         } catch (AuctionException ae)

         {

             // TODO: handle exception

             System.err.println(ae.getMessage());

         }

     }

 }


  catch和throw同时使用来处理异常的方法是在大型企业中比较常用的。


  java的异常跟踪栈


  异常对象的printStackTrace方法用于打印异常的跟踪栈信息,根据printStackTrace方法的输出结果,我们可以找到异常的源头,并跟踪到异常一路触发的过程。


  虽然printStackTrace()方法可以很方便地追踪异常的发生状况,可以用它来调试,但是在最后发布的程序中,应该避免使用它。而应该对捕获的异常进行适当的处理,而不是简单的将信息打印出来。


  总之,要合理使用异常。


以上就是动力节点java学院小编介绍的“java异常处理机制详解”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。



选你想看

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

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

先测评确定适合在学习

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