• javaday21_异常(自定义异常)


    异常:

    异常的继承体系:

    Throwable 在java.lang中。

    Throwable 是所有错误或异常的超类,所以它下面有两个大的子类---Error错误类,---Exception异常类。(我们平时不会关心错误,而是关心异常类。)

    Throwable(类) <--Exception (类)

            <--Error (类)        

    Error 和 Exception 的区别:

    什么是错误,什么是异常呢?

    Error 一般都是大问题,例如,开辟的内存过大之类,这样的一般都要修改代码!

    Exception  一般都是小问题,例如,数组越界之类的,这样的一般将异常处理掉就可以了。

    错误在运行的时候才会发生。

    Exception 异常,的解决方法是:将异常处理掉,就可以了。

    Error 错误,的解决方法是: 修改程序。 

    所以,我们一般处理的也都是异常,如果是Error 就只能改代码了。

    在Exception异常 下面还有个子类 --RuntimeException 类。

    我们主要说 Exception 和 RuntimeException !

    异常对象的产生原因 和 处理方式:

    如果最终 main 到了 JVM  的话,

    它又做了两件事

    1,将异常信息,以红色字体输出到控制台。 

    2,将程序停止结束。  

    如果在这个过程中,有人处理 这个异常的话,就不会出现抛到上一级的情况,那么代码也就可以继续执行了。

    注: 当抛出到上一级的时候,剩余的程序都不会再执行了

    方法内部抛出异常的 关键字 throw :

    抛出的对象,必须是Exception 或者 它的子类对象。  

     1 package cn.zcb.demo04;
     2 
     3 public class Test {
     4     public static void main(String[] args) {
     5         int arr[] = {1,2,3};
     6         int a = getNum(arr);
     7         System.out.println(a);
     8 
     9     }
    10     public static int getNum(int []arr){
    11         if(arr == null){
    12             throw new Exception("传递的数组不存在");
    13         }
    14         if(arr.length == 0){
    15             throw new Exception("数组中为任何元素");
    16          }
    17         int ret = arr[3];
    18         return ret;
    19     }
    20 
    21 
    22 }
    使用throw来抛出异常!

    此时的程序还是有bug 的。继续看下面:

    声明异常的 关键字 throws

    上面的throw + 对象是用来抛出异常的。

    这里的throws是用来写在方法的声明上的。声明此方法可能会出现异常。

    当调用者调用一个可能出现异常的方法的时候,它就必须处理该异常,如果不处理就会编译失败!

    例如:

     1 package cn.zcb.demo04;
     2 
     3 public class Test {
     4     public static void main(String[] args) {
     5         int arr[] = {1,2,3};
     6         int a = getNum(arr);//此时main 调用了可能出现异常的方法getNum,但是却没有处理该异常。于是就编译失败了!
     7         System.out.println(a);
     8 
     9     }
    10     public static int getNum(int []arr) throws Exception{
    11         if(arr == null){
    12             throw new Exception("传递的数组不存在");
    13         }
    14         if(arr.length == 0){
    15             throw new Exception("数组中为任何元素");
    16          }
    17         int ret = arr[3];
    18         return ret;
    19     }
    20 
    21 
    22 }
    调用者不处理异常,就出现编译失败了。

    注:Exception 类的异常必须要声明异常,但是RuntimeException及其子类不用声明异常

    异常的处理方式 try -catch-finally :

    之前,遇到异常都是一个字:往上抛,最后抛给了JVM,然后程序就终止了。

    下面我们使用异常的另一个  处理方式 try -catch!

    catch 中执行之后,就是处理了异常了,就不会往上面抛了。

    注:finally 是一定会执行的。

    异常的处理方式 多catch 捕获:

    指的是调用的方法可能有多个 异常产生,这时可以用多个catch 。

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args){
     5 //        int arr[] = null;
     6         int arr[] = new int[0];
     7         try {
     8             int a = getNum(arr);
     9             System.out.println(a);
    10         }catch (NullPointerException e){
    11             System.out.println(e);
    12         }catch (ArrayIndexOutOfBoundsException e){
    13             System.out.println(e);
    14         }
    15     }
    16     public static int getNum(int []arr)throws NullPointerException,ArrayIndexOutOfBoundsException {
    17         //因为传来的参数是 引用类型,因此肯定要判断是否为空
    18         if(arr == null){
    19             throw new NullPointerException("数组不存在!");
    20         }
    21         if(arr.length <=3){
    22             throw new ArrayIndexOutOfBoundsException("数组没有3索引");
    23         }
    24 
    25         int ret = arr[3];
    26         return ret;
    27     }
    28 
    29 
    30 }
    View Code

    catch() 的顺序:

    1,平级之间的异常( 例如NullPointerException 和 NoSuchElementExceptino 和 ArrayIndexOfBoundsException):

    平级之间,书写是可以没有顺序的。

    2,有继承关系的异常(NullPointerException 和 Exception):

    平级之间,书写是有顺序的。

    高级应该写在下面。

    它的原因是多态调用。 如果将Exception写在上面的话,那么下面的异常就永远也起不到作用了!

    关于 try-except-finally 中的finally :

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args){
     5         try {
     6             func(0); //产生异常
     7 //            func(1);//不产生异常!
     8         }catch (Exception e){
     9             System.out.println(e);
    10         }finally {
    11             System.out.println("无论产生异常与否,我是一定会被执行的“");
    12         }
    13 
    14 
    15     }
    16     public static void func(int a) throws Exception{
    17         if( a == 0){
    18             throw new Exception("异常产生");
    19         }
    20     }
    21 
    22 }
    View Code

    finally 只有一种情况不执行,就是用代码将 JVM 停止:System.exit(0);  

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args){
     5         try {
     6 //            func(0); //产生异常
     7             func(1);//不产生异常!
     8             System.exit(0);
     9 
    10         }catch (Exception e){
    11             System.out.println(e);
    12             System.exit(0);
    13         }finally {
    14             System.out.println("无论产生异常与否,我是一定会被执行的“");
    15         }
    16 
    17 
    18     }
    19     public static void func(int a) throws Exception{
    20         if( a == 0){
    21             throw new Exception("异常产生");
    22         }
    23     }
    24 
    25 }
    费尽心机,就是为了使finally 不执行。哈哈哈

    总结:一般finally 都是一定执行的,无论异常产生与否,除非你刻意不让它执行!

    那么finally 的作用是什么呢?它可以释放资源! 后面IO流中会有涉及!

    try-catch 和 throws 两种处理方式:

    调用者调用一个可能产生异常的方法的时候,它必须要做出处理,

    它有两种选择,

    一是不管它,在自己函数声明的地方加上throws,这时,如果产生异常,异常会自动的抛给上一级,最后到JVM。

    二是使用try-catch ,它会处理异常,然后继续执行程序。

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args) throws Exception{
     5         func_P();
     6     }
     7     public static void func_P() throws Exception{
     8         func(0);
     9     }
    10     public static void func(int a) throws Exception{
    11         if( a == 0){
    12             throw new Exception("异常产生");
    13         }
    14     }
    15 }
    对于异常,使用throws处理方式!
     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args){
     5         func_P();
     6     }
     7     public static void func_P() {
     8         try {
     9             func(0);
    10         }catch (Exception e){
    11             System.out.println(e);
    12         }
    13     }
    14     public static void func(int a) throws Exception{
    15         if( a == 0){
    16             throw new Exception("异常产生");
    17         }
    18     }
    19 }
    try-catch 处理异常方式!

    下面代码比上面好,下面代码不会终止程序,而上面代码会终止程序!

    因此处理异常,我们应该使用try-catch !

    注意:

    对于可能会产生异常的方法,对于Exception 异常,方法自己  必须要声明该异常,但是对于RuntimeException 及其子类的异常,可以不声明!!!

    异常 分类:

    异常分为 编译时异常 运行时异常!!!

    运行时异常 指的是 RuntimeException 类及其 子类 ,其他的基本都是编译时异常。

    补:异常的继承关系:

    Throwable(类) <--Exception (类) <- RuntimeException 类。

            <--Error (类)       

    运行时异常是不需要进行 throws语句声明的!即我们前面说的----对于RuntimeException 及其子类,可以不进行throws声明。

    调用也不需要对其处理,

    具体代码如下:

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args){
     5         func(0); //2 调用者也不需要进行处理 !
     6     }
     7     public static void func(int a){  //1,这不需要写 throws声明语句!
     8         if( a == 0){
     9             throw new RuntimeException("异常产生");
    10         }
    11     }
    12 }
    View Code

    那么,它这样设计的目的是什么呢?

    是因为运行异常本身,就不能发生,这时候要做的是停止程序,修改源代码。

    因为运行异常一旦发生,后面的代码在执行是没有意义的。

    运行时异常就是让程序人员停下来改代码的。

    它和其他的异常都不太一样!

    运行时异常和 其他异常的区别:

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args) {
     5         try{
     6             func(0);
     7         }catch (Exception e){
     8             e.printStackTrace();
     9         }
    10     }
    11     public static int func(int a) throws Exception{
    12         if(a == 0){
    13             throw new Exception("异常!");
    14         }
    15         return  0;
    16     }
    17 }
    18 /*
    19 * 一般异常 输出
    20 java.lang.Exception: 异常!
    21     at cn.zcb.demo05.Test.func(Test.java:13)
    22     at cn.zcb.demo05.Test.main(Test.java:6)
    23 
    24 Process finished with exit code 0
    25 * */
    非运行时异常,exit 码为0 ,程序和正常返回
     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args) {
     5         func(0 );  //调用者不需要进行 try catch  !!!
     6     }
     7     public static int func(int a) {
     8         if(a == 0){
     9             throw new RuntimeException("异常!");
    10         }
    11         return  0;
    12     }
    13 }
    14 /*
    15 * 运行时异常 输出
    16 Exception in thread "main" java.lang.RuntimeException: 异常!
    17     at cn.zcb.demo05.Test.func(Test.java:9)
    18     at cn.zcb.demo05.Test.main(Test.java:5)
    19 
    20 Process finished with exit code 1
    21 * */
    运行时异常,exit 返回 1

    子类重写父类的方法 的异常问题:

    总结:

    一句话:父类抛了(声明)异常,子类可以抛(声明)但不能抛(声明)过头;父类没有(声明)抛,子类永远不能(声明)抛。

    异常和错误 的超类 ---Throwable 类  的三个方法:

    这三个方法都是和 “信息” 有关系,这个“信息” 是指的是 出现在输出框中的红色字!

    String getMessage();  //对异常信息的简短描述

    String toString();  对异常信息的详细描述

    void printStackTrace();  //将异常信息 追踪到标准的 错误流 ! 异常信息是最详细的(也是JVM默认的调用方法!)。

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args){
     5         try {
     6             func(0);
     7         }catch (Exception e){
     8             System.out.println(e.getMessage()); //简短异常信息
     9             System.out.println(e.toString()); //异常信息 详细描述 !相对上面 有了具体哪个类
    10             e.printStackTrace(); //异常信息,最详细!  
    11         }
    12 
    13     }
    14     public static void func(int a) throws Exception{
    15         if( a == 0){
    16             throw new Exception("异常产生");
    17         }
    18     }
    19 }
    View Code

    自定义异常:

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args) {
     5         int avg = getAvg(10,20,30,40);
     6         System.out.println(avg);
     7 
     8     }
     9     /**
    10      * 当计算成绩时候,如果传递是 负数,应该停止再计算了!  需要抛出异常!
    11      * 但是,由于Java 中没有现成的 关于负数的异常,所以我们自定义异常!
    12      */
    13     public static int getAvg(int ...score){
    14         int sum = 0;
    15         for (int s:score){
    16             sum+= s;
    17         }
    18         return sum/score.length;
    19     }
    20 }
    View Code
     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args) {
     5         int res = getAvg(10,20,30,40,-10);
     6         System.out.println(res);
     7 
     8     }
     9     public static int getAvg(int...scores){
    10         int sum = 0;
    11         for (int score:scores){
    12             if(score <0 ){
    13                 throw new MyException("负数异常,成绩不能为负数!");
    14             }
    15             sum += score;
    16         }
    17         return sum/scores.length;
    18     }
    19 }
    Test.java
    package cn.zcb.demo05;
    
    //关于 负数的异常,它比较适合使用 RuntimeException 异常,
    //它只要是有 负数,我就直接把 你的程序给你停止(exit 码非0)了!
    public class MyException extends RuntimeException {
        //必须要 继承(继承Throwable 或其子类!),因为这样才会有可抛性!
        public MyException(){};
        public MyException(String s){}
    
    }
    MyException.java

    此时的问题是 当异常产生时候,没有输出 我们new 时候的String。

    上面也说了,我们这时候应该将这个参数传给super() ,传给上一级,它会一级一级的传,最后是在超类 Throwable中最终将这个字符串 输出到控制台!

    代码最终如下:

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args) {
     5         int res = getAvg(10,20,30,40,-10);
     6         System.out.println(res);
     7 
     8     }
     9     public static int getAvg(int...scores){
    10         int sum = 0;
    11         for (int score:scores){
    12             if(score <0 ){
    13                 throw new MyException("负数异常,成绩不能为负数!");
    14             }
    15             sum += score;
    16         }
    17         return sum/scores.length;
    18     }
    19 }
    Test.java
     1 package cn.zcb.demo05;
     2 
     3 //关于 负数的异常,它比较适合使用 RuntimeException 异常,
     4 //它只要是有 负数,我就直接把 你的程序给你停止(exit 码非0)了!
     5 public class MyException extends RuntimeException {
     6     //必须要 继承(继承Throwable 或其子类!),因为这样才会有可抛性!
     7     public MyException(){
     8         super();
     9     }
    10     public MyException(String s){
    11         super(s);
    12     }
    13 
    14 }
    MyException.java

    注:大部分的异常都是 RuntimeException 异常!

    当然,也可以不自定义异常,如下代码:

     1 package cn.zcb.demo05;
     2 
     3 public class Test {
     4     public static void main(String[] args) {
     5         int res = getAvg(10,20,30,40,-10);
     6         System.out.println(res);
     7 
     8     }
     9     public static int getAvg(int...scores){
    10         int sum = 0;
    11         for (int score:scores){
    12             if(score <0 ){
    13                 throw new RuntimeException("负数异常,成绩不能为负数!");
    14             }
    15             sum += score;
    16         }
    17         return sum/scores.length;
    18     }
    19 }
    View Code
  • 相关阅读:
    Minimum Size Subarray Sum 最短子数组之和
    mutiplemap 总结
    Remove-Invalid-Parentheses-题解
    Splay-Tree理解
    Subsets LeetCode总结
    Trie树理解
    Treap树理解
    Trie树之C-实现
    word-ladder总结
    Javascript 对象
  • 原文地址:https://www.cnblogs.com/zach0812/p/11915578.html
Copyright © 2020-2023  润新知