异常

异常

1、异常的概念
2、异常体系图★
3、常见的异常
4、异常处理的概念
5、异常处理的分类 ★
6、自定义异常【了解】
7、throw和throws的对比【面试题】

异常的概念

异常的体系图

常见的运行异常介绍

NullPointerException 空指针异常
    当试图使用null对象的属性或方法时
ArrayIndexOutOfBoundsException 数组下标越界异常
    当试图使用数组的索引超过范围:0——length-1
ClassCastException 类型转换异常
    当试图将不是该类型的实例强转成该类型
ArithmeticException 数学运算异常
    除数为0时
NumberFormatException 数字格式不正确
    当试图将字符串转换成数值时,如果该字符串不是有效的数值格式

异常处理的概念

处理程序中发生的不正常现象,称为异常处理

异常处理好处

a、提高用户的体验性(可打印友好提示)
b、让正常的代码和容易出错的代码进行了分离,提高代码的语义性和维护性
c、让try catch块后面的语句继续执行

异常处理的分类 ★

方式一:自己处理

语法

try{
①
//容易出现异常的代码②
③
}catch(异常类型A e){
    //处理语句1 ④
}catch(异常类型B e){
    //处理语句1 ⑤
}catch(异常类型C e){
    //处理语句1 ⑥
}
finally{
    //最后一定执行的语句 ⑦
}

执行顺序

如果 try 出现了异常,则 try 块中下面的语句将不再执行,而是执行 catch 块的语句,最后执行 finally 块的语句

如果 try 未出现异常,则 try 块中下面的语句需要执行,catch块的语句不再执行,最后执行 finally 块的语句

注意事项

  1. catch块可以省略
  2. 也可以多个,但如果catch块中有父类异常类型,必须放在最后!
  3. finally块可以省略

例1

import java.util.Scanner;
public class TestException4 {
    public static void main(String[] args) {
        Scanner input  = new Scanner(System.in);
//        try部分运行到错误处,将不会再往下执行
        try{
//            其中有可能有多种错误,则后面可放多个 catch 块
            System.out.println("请输入a:");
            String a = input.next();
            System.out.println("请输入b:");
            String b= input.next();
            //判断两个字符串是否相等
//            a=null;// 若将a赋成null,则不管是什么错误,下面只会报空指针错误,因为try下面部分都不会再执行
            if(a.equals(b)){
                System.out.println("相等");
            }
            //将字符串转换成int类型
            int num1 = Integer.parseInt(a);
            int num2 = Integer.parseInt(b);
            //数学运算
            System.out.println("div="+num1/num2);//容易出现异常
            System.out.println("哈哈");
//          若某种错误忘记是哪一种,则直接用 Exception 父类,但这个catch块要放到最后
            System.out.println(args[0]);
        }catch(NumberFormatException e){
            System.out.println("数字格式不正确吧");
        }catch(ArithmeticException e){
            System.out.println("除数为0了吧!");
        }catch(NullPointerException e){
            System.out.println("空指针了吧");
        }catch(Exception e){
//            catch块中有父类异常类型,必须放在最后
            System.out.println("下标越界吧");
        }finally{
//            最后一定要执行的语句
            System.out.println("try catch块后面的语句");
        }
    }
}

例2

public class TestException1 {
    static int method(){
        try {
            String[] names = new String[3];
            if(names[1].equals("john")){
                System.out.println(names[1]);
            }
            else{
                names[3] = "lucy";
            }
            return 1;
        } catch (ArrayIndexOutOfBoundsException e) {
            // TODO Auto-generated catch block
            return 2;
        } catch (NullPointerException e) {
            // TODO Auto-generated catch block
            return 3;
        } finally{
//            若此句不注释,则无论怎么执行都是只返回4,因为try catch无论怎样,最后总是执行finally块中的
//            return 4;
            //此时返回3并且输出222222
            System.out.println("222222");
        }
        //此句不会再执行
        System.out.println("333333");
    }
    public static void main(String[] args){
//        Scanner input = new Scanner(System.in);
//        int  i=input.nextInt();
//        System.out.println(i);
        System.out.println(method());
    }
}

总结

  1. 并不是try块中的语句越多越好,因为会影响效率(try要检测错误类型,所以会影响效率)

  2. 尽量使用多个catch代替多个try catch(将出错部分都放入try中,然后多个catch处理)

方式二:抛给他人处理

语法

修饰符 返回类型 方法名(参数列表) throws 异常类型A{
    //容易出现异常的代码
}
异常类型A为 方法中出现的异常类型或其父类类型

执行机制

  1. 将异常抛给调用方,调用方可以继续处理,如果继续往上抛,可以一直抛到jvm,jvm则最后处理方式:打印错误堆栈日志!

  2. 如果对异常不进行任何处理,则默认采取的方式为抛出的方式

  3. 子类方法抛出的异常要么相同,要么为其子类类型

例1

public class TestException5 {
    public static void main(String[] args ) throws Exception {
        method1();
    }
    private static void method1() throws Exception {
        method2();
    }
    private static void method2() throws Exception {
        method3();
    }
    private static void method3() throws Exception {
        method4();
    }
    private static void method4() throws Exception{
        int[] arr = {1,2,3};
        System.out.println(arr[3]);//下标越界异常
    }
}

例2

class Son extends Father{
    @Override
    public void method() throws NullPointerException {
        super.method();
    }
}
class Father{
    public void method() throws RuntimeException{
    }
}

生成异常对象

  1. 系统自动生成,只能针对系统定义好的异常类型
  2. 手动抛出,可以针对系统定义好的异常类型或自定义的异常类型
    throw new 异常类型();

public class TestException7 {
    public static void main(String[] args) {
        Scanner input  = new Scanner(System.in);
        System.out.println("年龄:");
        int age = input.nextInt();
        if(age>120 || age<0){
            //生成一个异常对象
//            AgeIllegalException ae = new AgeIllegalException("年龄不合法!");
//            throw ae;
//            throw new AgeIllegalException("年龄不合法!");  //与上面两句效果相同
            try {
                //下面两句效果一样,因此自定义异常可有可无
                throw new RuntimeException("年龄不合法!");
//                throw new AgeIllegalException("年龄不合法!");
            } catch (Exception e) {
//                e.printStackTrace();
                System.out.println("出错了,信息:"+e.getMessage());
            }
        }
        System.out.println("年龄是:"+age);
    }
}
class AgeIllegalException extends RuntimeException{
    private static final long serialVersionUID = 1L;
    public AgeIllegalException(String msg){
        super(msg);
    }
    public AgeIllegalException(){
    }
}

面试

  1. 生成异常方式和区别
  2. throw 和 throws对比
意思 后面跟的东西 放的位置
throw 手动生成异常 异常对象 方法体中,一般搭配if使用
throws 异常生成的另一种方式 异常类型 方法声明处

   转载规则


《异常》 文超 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
常用类 常用类
常用类
2020-03-31
下一篇 
java面向对象(下) java面向对象(下)
忘了从某天决定学学java,刚开始笔记都记在了本子上,实在不想再用电子版重新写了,就写从面向对象(下)开始写吧.陆陆续续终于把面向对象下补充完了,后续接着更新吧~ 面向对象(下)1、内部类 2、枚举 3、注解内部类理解一个类中又完整的嵌套了
2020-03-22
  目录