异常

异常

概念:程序中出现的不正常现象就是异常

继承体系

异常中的顶级父类:

Java.lang.Throwable : 所有有异常和错误的父类
    |--Java.lang.Error : 所有错误的父类
    |--Java.lang.Exception : 所有异常的父类
        |--Java.lang.RuntimeExceptiion : 所有运行时异常的父类

顶级父类Throwable的方法

String toString() //返回详细异常信息
String getMessage() //返回简单异常信息
void printStackTrace() //异常信息追踪到标准的错误流,最详细,综合了以上两个另外还有异常发生的代码行   

以上方法为顶级父类的方法,其子类可直接使用。

默认的异常处理情况

默认情况即无人工干预的情况,JVM的处理方式

  1. 方法中异常发生,处理不了,向上抛出给调用者,调用者也处理不了,抛给jvm

jvm看你们都不处理,那我直接输出信息,结束程序。之后的代码不在执行!

  1. 没有异常,继续执行程序

try...catch异常处理

try catch的异常处理的格式写法 :

try{
    被检测的代码
    可能发生异常的代码
}catch(异常类的类名  变量名){
    异常的处理方式 : 写什么都可以
    定义变量,创建对象,调用方法,循环,判断...
    只要写了catch,异常就被处理掉了
}
public static void main(String[] args) {
        int[] arr = {1};
        //try  catch异常处理
        try {
            int i = getNum(arr);
            System.out.println("i = " + i);
        }catch (Exception ex){   //括号中写异常类型,不知道些什么直接写异常顶级父类,(多态)
            System.out.println("异常被处理掉");
        }
        System.out.println(111);
    }

    public static int getNum(int[] arr){
        return arr[1] + 10;
    }

多catch并行处理

异常处理的代码中 : try 可以跟随多个catch

好处:针对方法中出现不同的异常可以分开处理

public static void main(String[] args) {
    /**
    *   myExec出现2个异常
    *   写2个catch分别捕获异常
    */
    try {
        	myExec(0);
        }catch (NullPointerException ex){
        	System.out.println("处理空指针异常");
        }catch (ArrayIndexOutOfBoundsException ex){
        	System.out.println("处理越界异常");
        }
    }

    /**
    * 定义方法,目的引发异常
    * 传递参数 : 对参数进行判断  会出现不同的异常
    */
    public static void  myExec(int i){
    if ( i == 0){
        //引发空指针异常
        String s = null;
        int len = s.length();
    }else {
        //引发越界异常
        int[] arr = {};
        int a = arr[0];
    }
}

多个catch处理异常的时候,写法特别注意 : 如果catch中的异常类没有关系,先写后写没有区别, catch中的异常类有继承关系,父类写在最下面

throw和throws 关键字的使用

  • throw只能写在方法的内部,后面跟随对象的创建
  • throws只能写在方法的定义上即方法的后面,后面跟随异常类名
public static void main(String[] args) {
       /**
         *   getArea()调用方法,方法上有异常
         *   只能处理,不处理编译失败
         *   在main的方法上加throws 异常没有处理,交给JVM处理
         *   try catch处理
         */
    try {
        int area = getArea(-10);
        System.out.println(area);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
     * 功能: 计算正方形的面积
     * 需要参数 : 边长
     * 语法 : 方法的内部出现了异常,必须在方法定义上暴露
     */
public static int getArea(int length) throws  Exception{
    if (length <= 0)
        //数据错误,导致后面的计算不能进行
        //内部出现问题
        throw new Exception("边长不存在");
    return length * length;
}

finally代码块

  • finally代码块跟随try ... catch使用,也有跟随try使用

  • finally语句一定会执行,除非结束jvm

  • 主要用于释放资源(数据库连接等)

    public static void main(String[] args) {
        try {
            int[] arr = {1};
            System.out.println(arr[0]);
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            //后期用于资源的释放
            System.out.println("这里的代码,必须执行");
        }
    }
    

两个恶心的题目

public class ExceptionText {
    public static void main(String[] args) {
        System.out.println(finallyTest1());//輸出3

        System.out.println(finallyTest2());//输出1
    }

//题1:    
    public static int finallyTest1() {

        try {
            return 1;    //没有异常,catch里肯定不会执行,准备返回1,但finally的3将其覆盖
        }catch (Exception ex){
            return 2;
        }finally {
            return 3;
        }
    }
    
//题2:
    public static int finallyTest2() {

        int a = 1;
        try {
            return a;          //此处a已经变为1,即return 1,即将返回;
                               // finally执行后a=2;不关我return 1的事
        }catch (Exception ex){
            return a;
        }finally {
            ++a;
        }
    }


}

RuntimeException异常

Exception
    |--RuntimeExceptiion
       |-- NullPointerException
       |-- ... 

RuntimeException和他的所有子类,都称为运行异常,非子类的称为编译异常

  • 编译异常 : 方法出现编译异常,调用者必须处理,否则编译失败.处理方式可以是try catch或者是throws都可以,程序内部抛给你的。
  • 运行异常 : 方法出现运行异常,方法的定义上,不需要throws声明,调用者也不需要处理这个异常,直接修改代码

不要处理运行异常 : 程序一旦发生运行异常,请程序人员修改源码

  • 常见的运行异常
    • NullPointerException 空指针
    • IndexOutOfBoundsException 越界异常
    • ClassCastException 类型强制 (类型转换异常)
    • IllegalArgumentException 非法的参数异常

自定义异常

Java官方已经定义了大量的异常类,但是依然不够,在做项目的时候,Jdk中没有与我们需要相匹配的异常类,故需要我们自己写。

  • 自定义前提继承Exception或者RuntimeException,(只有Exception和他的子类,才具有可抛出性)
  • 自定义的类中,构造方法,super调用父类构造方法,传递异常信息
/**
 *  自定义的异常类
 *    成绩负数的异常
 *    继承哪个父类呢
 *
 *    自定义异常信息 : 继承父类 RuntimeException 带有String类型的构造方法 (String 异常信息)
 */
public class ScoreException extends RuntimeException{
    public ScoreException(String s){
        super(s);
    }
}
 public static void main(String[] args) {
       // int[] arr = {1};
        //System.out.println(arr[2]);
        int avg = getAvg(-100,2);
        System.out.println("avg = " + avg);
    }

    /**
     * 计算成绩的平均分
     */
    public static int getAvg(int math,int chinese){
        //判断成绩的数值
        if ( math < 0 || chinese < 0)
            //手动抛出,自己定义的异常
            throw new ScoreException("成绩不存在");

        return  (math + chinese) / 2;
    }

posted @ 2021-07-31 21:31  jewww  阅读(175)  评论(0)    收藏  举报