自定义异常与编译时运行时异常

来源:互联网 发布:yum 安装pip 编辑:程序博客网 时间:2024/06/11 14:03

   学到异常处理了,于是想记录下Java异常处理的细节,以增加对异常处理的印象。

    Java常见的异常类之间的继承关系:

    

      (仿李刚老师的《疯狂Java讲义》异常章节的图)

      Java的异常被分为两大类:Checked异常(编译时出现异常)和Runtime(运行时异常)。

           1、编译时被检测的异常,除了特殊子类RuntimeException体系的,只要是Exception和其子类都是。
         这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。
           2、编译时不检测异常(运行时异常),就是Exception中的RuntimeException和其子类,这种问题的发生,让                   功能无法继续,运算也无法进行,更多是因为调用的原因导致的。或者引发程序内部状态改变,导致异                       常。这种问题一般不处理,直接编译通过,在运行时,调用者调用时引发异常从而程序强制停止,此时调用者即可对异常进行修正。

            异常Demo演示:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class First  
  2. {  
  3.     private int num;  
  4.       
  5.     public void change(String str)  
  6.     {  
  7.         int a = Integer.parseInt(str);  
  8.         this.num = a;  
  9.     }  
  10.       
  11.     public static void main(String[] args)  
  12.     {  
  13.         First f = new First();  
  14.         f.change("one");  
  15.     }  
  16. }  
  17. /* 
  18. 编译这段代码后,运行出现NumberFormatException异常,这是一个运行时异常 
  19. */  
增加一个自定义的异常处理类:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class MyException extends Exception    //自定义一个异常类,  
  2. {  
  3.     /*如果将MyException继承自RuntimeException,就没有后面的故事了,呵呵! 
  4.      *这样后,MyException就是一个运行时异常,从下面的叙述中, 
  5.      *你应该能看出运行时异常和编译时异常的区别吧 
  6.     */  
  7.         public MyException(){}  
  8.         public MyException(String msg)  
  9.         {  
  10.             super(msg);  
  11.         }  
  12. }  
  13. public class First  
  14. {  
  15.     private int num;  
  16.       
  17.     public void change(String str)  
  18.     {  
  19.         try   
  20.         {  
  21.             int a = Integer.parseInt(str);  
  22.             this.num = a;  
  23.         }  
  24.         catch(Exception e)  
  25.         {  
  26.             throw new MyException("You should pass a integer string.");  //抛出自定义异常  
  27.         }  
  28.   
  29.     }  
  30.       
  31.     public static void main(String[] args)  
  32.     {  
  33.         First f = new First();  
  34.         f.change("one");  
  35.     }  
  36. }  
  37. /* 
  38. 编译这段代码后,出现错误: 
  39. First.java:22: error: unreported exception MyException; must be caught or declared to be thrown 
  40.                         throw new MyException("You should pass a integer string.");  //?????????? 
  41. ?? 
  42.                         ^ 
  43. 1 error 
  44. */  

    "未报告的异常,必须被捕获或者声明",此处编译不能通过,对于自定义的异常类属于编译时异常,需要在函数在函数出进行声明,代码改成如下:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class MyException extends Exception    //自定义一个异常类  
  2. {  
  3.     public MyException(){}  
  4.     public MyException(String msg)  
  5.     {  
  6.         super(msg);  
  7.     }  
  8. }  
  9. public class First  
  10. {  
  11.     private int num;  
  12.       
  13.     public void change(String str) throws MyException     //在方法声明上抛出,是为了告诉调用者,你注意了,我有问题  
  14.     {  
  15.         try   
  16.         {  
  17.             int a = Integer.parseInt(str);  
  18.             this.num = a;  
  19.         }  
  20.         catch(Exception e)     
  21.         {  
  22.             throw new MyException("You should pass a integer string.");  //抛出自定义异常  
  23.         }  
  24.   
  25.     }  
  26.       
  27.     public static void main(String[] args)  
  28.     {  
  29.         First f = new First();  
  30.         f.change("one");  
  31.     }  
  32. }  
  33. /* 
  34. 编译这段代码后,出现错误: 
  35. First.java:30: error: unreported exception MyException; must be caught or declared to be thrown 
  36.                 f.change("one"); 
  37.                         ^ 
  38. 1 error 
  39.  
  40. */  
    为什么还是不能编译通过呢?一开始在change()方法体内遇到throw new MyException("You should pass a integer string.");  准备抛出异常,可是change()方法没有显示声明这个异常,对于编译性的异常,需要显示进行声明,让JVM知道后续程序运行时该怎么处理。后来在change()方法声明了我的自定义异常:public void change(String str) throws MyException,所以change()方法中的MyException异常被抛到调用change()方法的main主函数中,所以出现了上面的错误,因而也需要在main主函数声明MyException。下面是正确代码:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class MyException extends Exception    //自定义一个异常类  
  2. {  
  3.         public MyException(){}  
  4.         public MyException(String msg)  
  5.         {  
  6.             super(msg);  
  7.         }  
  8. }  
  9. public class First  
  10. {  
  11.     private int num;  
  12.       
  13.     public void change(String str) throws MyException  
  14.     {  
  15.         try   
  16.         {  
  17.             int a = Integer.parseInt(str);  
  18.             this.num = a;  
  19.         }  
  20.         catch(Exception e)  
  21.         {  
  22.             throw new MyException("You should pass a integer string.");  //抛出自定义异常  
  23.         }  
  24.   
  25.     }  
  26.       
  27.     public static void main(String[] args) throws MyException  //这里抛出自定义异常,但我们在程序开发时,通常不这么做  
  28.     {  
  29.         First f = new First();  
  30.         f.change("one");  
  31.     }  
  32. }  
  33. /** 
  34. Exception in thread "main" MyException: You should pass a integer string. 
  35.         at First.change(First.java:22) 
  36.         at First.main(First.java:30) 
  37. */  
     编译、运行上面的代码后,最终的MyException异常被抛给JVM,JVM打印出异常跟踪栈。对于这样的异常,可以进行必要的try catch操作。如:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class MyException extends Exception    //自定义一个异常类  
  2. {  
  3.         public MyException(){}  
  4.         public MyException(String msg)  
  5.         {  
  6.             super(msg);  
  7.         }  
  8. }  
  9. public class First  
  10. {  
  11.     private int num;  
  12.       
  13.     public void change(String str) throws MyException // 注:如果MyException是一个RuntimeException, 这里就不用声明抛出了  
  14.     {  
  15.         try   
  16.         {  
  17.             int a = Integer.parseInt(str);  
  18.             this.num = a;  
  19.         }  
  20.         catch(Exception e)  
  21.         {  
  22.             throw new MyException("You should pass a integer string.");  //抛出自定义异常  
  23.         }  
  24.   
  25.     }  
  26.       
  27.     public static void main(String[] args)  
  28.     {  
  29.         First f = new First();  
  30.         try  
  31.         {  
  32.                  f.change("one");  
  33.         }  
  34.         catch(MyException e)   //直接捕获并处理了  
  35.         {  
  36.             System.out.println("error: " + e.getMessage());  
  37.         }  
  38.     }  
  39. }  
    再对比一个编译时异常的例子:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. import java.io.IOException;  
  2. import java.io.FileInputStream;  
  3. public class Second  
  4. {  
  5.     public void fileTest()  
  6.     {  
  7.         FileInputStream fis = null;  
  8.         try   
  9.         {  
  10.             fis = new FileInputStream("no-such-a-file.txt");  
  11.         }  
  12.         catch(Exception e)  
  13.         {  
  14.             throw new IOException();  
  15.         }  
  16.   
  17.     }  
  18.       
  19.     public static void main(String[] args)  
  20.     {  
  21.         Second f = new Second();  
  22.         f.fileTest();  
  23.     }  
  24. }  
也会出现:

Second.java:14: error: unreported exception IOException; must be caught or declared to be thrown
                        throw new IOException();
                        ^
1 error

    IOException是编译时异常,这样的错误, 所以你还是得在方法体上声明IOException,对于RuntimeException是不需要声明的。See next:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. import java.io.IOException;  
  2. import java.io.FileInputStream;  
  3. public class Second   
  4. {  
  5.     public void fileTest() throws IOException  
  6.     {  
  7.         FileInputStream fis = null;  
  8.         try   
  9.         {  
  10.             fis = new FileInputStream("no-such-a-file.txt");  
  11.         }  
  12.         catch(Exception e)  
  13.         {  
  14.             throw new IOException();  
  15.         }  
  16.   
  17.     }  
  18.       
  19.     public static void main(String[] args)  throws IOException  
  20.     {  
  21.         Second f = new Second();  
  22.         f.fileTest();  
  23.     }  
  24. }  

    这样就不会在编译时出现情况了,这算是应该注意的一个小细节吧。

   下面再来看一个RuntimeException不需要声明的例子:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class MyException3 extends RuntimeException {  
  2.     private String message;  
  3.   
  4.     public MyException3() {  
  5.     }  
  6.   
  7.     public MyException3(String mess) {  
  8.         message = mess;  
  9.     }  
  10.   
  11.     public String getMessage() {  
  12.         return message;  
  13.     }  
  14. }  
  15.   
  16. public class NotDeclareRuntimeExceptionTest {  
  17.       
  18.     public static void runtimeExceptionTest1(int n) {   //这里不用声名抛出的异常 MyException3  
  19.         if (n == 1) {  
  20.             throw new MyException3();  
  21.         } else {  
  22.             System.out.println("dd");  
  23.         }  
  24.     }  
  25.   
  26.     public static void main(String[] args) {  
  27.         System.out.println("ok");  
  28.     }  
  29.   
  30.   
  31. }  

参考博客:

http://www.blogjava.net/fancydeepin/archive/2015/10/15/382508.html 

http://blog.csdn.net/hguisu/article/details/6155636

0 0