异常
1、异常的概念
2、异常体系图★
3、常见的异常
4、异常处理的概念
5、异常处理的分类 ★
6、自定义异常【了解】
7、throw和throws的对比【面试题】异常的概念
.png)
.png)
异常的体系图
.png)
常见的运行异常介绍
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 块的语句
注意事项
- catch块可以省略
- 也可以多个,但如果catch块中有父类异常类型,必须放在最后!
- 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());
    }
}总结
- 并不是try块中的语句越多越好,因为会影响效率(try要检测错误类型,所以会影响效率) 
- 尽量使用多个catch代替多个try catch(将出错部分都放入try中,然后多个catch处理) 
方式二:抛给他人处理
语法
修饰符 返回类型 方法名(参数列表) throws 异常类型A{
    //容易出现异常的代码
}
异常类型A为 方法中出现的异常类型或其父类类型执行机制
- 将异常抛给调用方,调用方可以继续处理,如果继续往上抛,可以一直抛到jvm,jvm则最后处理方式:打印错误堆栈日志! 
- 如果对异常不进行任何处理,则默认采取的方式为抛出的方式 
- 子类方法抛出的异常要么相同,要么为其子类类型 
例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{
    }
}生成异常对象
- 系统自动生成,只能针对系统定义好的异常类型
- 手动抛出,可以针对系统定义好的异常类型或自定义的异常类型
 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(){
    }
}面试
- 生成异常方式和区别
- throw 和 throws对比
| 意思 | 后面跟的东西 | 放的位置 | |
|---|---|---|---|
| throw | 手动生成异常 | 异常对象 | 方法体中,一般搭配if使用 | 
| throws | 异常生成的另一种方式 | 异常类型 | 方法声明处 | 
 
                     
                     
                 
                        
                        