Exception:程序中不正常的行为被称为异常或者错误
    异常的体系结构:
        Throwable
            Error:程序员不能处理的情况,需要修改底层的源代码
            Exception:需要由程序员来进行处理的
                RuntimeException:在运行阶段出现的问题
                编译异常:在编译阶段就出现的问题

    处理异常的两种方式:
        自己解决:try...catch...finally
        让别人解决:throws

    创建异常对象
        new 异常类("错误信息")
        抛出异常对象  throw new 异常类("错误信息")

    注意事项:
        1、运行时异常可以抛出,不进行处理,让虚拟机处理
        2、如果父类抛出了异常子类覆盖父类的时候
            (1)不抛出任何异常
            (2)抛出和父类的方法一样的异常
            (3)抛出和父类方法一样的异常的子异常
        3、一个try可以匹配多个catch,如果catch的异常类之间存在继承关系,子类异常必须写在
            父类异常前面

        A.java ----->  编译器进行编译javac.exe -------> A.class ----------> 解释器运行java.exe
                       如果程序有问题就会出现编译异常
        ------> 字节码(机器码)

    异常和错误的区别
    异常:指在程序编译、运行期间发生了某种特殊情况(XXXXXException),我们可以对异常进行具体的处理
         如果不进行处理,程序就会结束运行
         System.out.println(10/0);
    错误:指程序在运行期间发生了某些错误(XXXXError),Error错误通常没有具体的处理方式,并且程序会结束
         运行,Error错误发生的往往是系统级别的问题,jvm所在的系统发生问题并且反馈给JVM,我们无法处理
         只能修改代码
         int[] arr = new int[102410241024];


    throw关键字
        抛出异常对象
        作用:可以使用throw关键字,在指定的方法中抛出指定的异常对象
        格式:throw new XXXXXException("填写异常产生的原因")
        注意:
            1、throw关键字必须写在方法的内部
            2、throw关键字后面new的对象必须时Exception 或者 Exception的子类
            3、throw关键字
                情况1:抛出的是检查异常,我们必须处理这个异常
                    throw new Exception("异常原因");
                    //我们必须手动处理这个异常
                    //处理异常的方式有两种    throws     try...catch....
                情况2:抛出的是运行时异常(RuntimeException 或者 RuntimeException的子类)
                     我们可以不进行处理,由jvm进行处理

    try...catch...finally 捕获异常(自己处理)
    java中对异常有针对性的语句进行捕获,可以对出现异常运行指定的方式的处理
    格式:
        try{
            //可能出现异常的代码(没有异常的代码也可以定义在try语句块中)
            //try语句块中,一旦出现了异常,则抛出异常的那个语句后面的代码就不执行了
            //疑似病例(可能得病了,也可能没有)
        }catch(异常类名 变量名){//数据类型 必须时异常类或者异常的子类
            //新冠确诊 匹配这个,才会执行代码,就会打印信息
            //就会进入隔离区
            //异常的处理语句,抓取到和异常类名一样的对象才会执行
        }catch(异常类名 变量名){
            //普通流感  匹配这个,才会执行代码,就会打印信息
        }finally{
            //不论是否有异常发生,finally里面的内容个都会执行(执行一遍)
        }
        System.out.println("1***");//一下的代码就可以正常执行了

        注意:
            1、try 存放的是可能出现异常的代码,异常有0个或者n个
            2、catch用来进行某种异常的抓去,实现对抓到的异常对象进行处理
               一个try可以匹配多个catch,catch是有顺序要求
               (1)如果多个catch的异常类之间没有继承关系,顺序可以随便写
               (2)如果多个catch之间存在继承关系,则子类异常必须放在父类异常的上面
            3、finally:不论是否有异常都会执行一


public static void main(String[] args) {
        try {
            int a = 10 / 0;
        }catch (ArithmeticException a){
            System.out.println("算术异常,除数不能为0");
        }catch (RuntimeException r){
            System.out.println("出现运行时异常");
        }catch (Exception e){
            System.out.println("出现异常");
        }finally {
            for(int i = 0; i < 10; i++){
                System.out.println(i);
            }
        }
        for(int i = 0; i < 10; i++){
            System.out.println("----------" + i);
        }
        System.out.println("程序执行完了");
    }


组合方式:
            1、try...catch...
            2、try...catch...finally
            3、try...catch...catch...finally
            4、try...finally

        throws抛出异常(交给别人处理)
            作用:
                当方法内部抛出异常对象的时候,我们必须处理这个异常对象
                如果使用throws的话就就将异常抛出了
                抛给谁?抛给方法的调用者进行处理
                如果到了主方法,还继续往外抛,则最终交给jvm(1、打印错误信息 2、中断程序的执行)

            格式:
                    public 返回值类型 方法名(参数列表)throws AaaaaaException,BbbbbException{
                        throw new AaaaaaException("产生的原因");
                        throw new BbbbbException("产生的原因");
                    }
            注意:
                throws关键字必须写在方法的声明出
                throws关键字后面必须时异常或者异常的子类
                方法内部如果抛出了多个异常对象,那么throws后面必须声明多个异常对象
                如果抛出多个异常对象存在子父类关系,就执行抛出父类异常

        throw和throws的区别
            java中的异常抛出
            throw: 将要产生的异常(动作)
            throws:声明一个将要抛出何种类型的异常(声明)

            throw 定义在方法的内部,后面跟的是异常对象
                  new 异常类的构造器(参数值);
                  同时只能抛出一个异常对象,抛出的异常对象后面的代码就不执行了
                  throw new XXXException("异常的原因")

            throws 定义在方法的声明上,后面跟的是异常的类型
                   后面可以跟多个异常类型
                  public static 返回值数据类型 方法名(参数列表)
                  throws XXXException,XXXException{
                  }


        异常在重写中的细节
        1、子类重写父类中的方法的时候,如果父类方法声明了异常,子类重写的方法
           可以声明和父类方法相同的异常或者声明父类异常的子类异常

        2、父类的方法没有抛出异常的时候子类重写的方法可以抛出异常,但是一般也不抛出
            如果子类产生了检查异常,则自己在方法的内部使用try...catch...进行处理
            不要抛出
            如果子产生了运行时异常,则不用不用自己处理,因为jvm会进行处理


        自定义异常
            1、创建类继承于Exception或者继承于它的子类
            2、在类中定义两个构造器,一个是没有参数的,一个是有String类型参数的
            3、分别在构造方法中调用对应的父类的构造方法

            如何使用自己定义的异常
                如果程序没有满足你的需求的时候,可以抛出一个自定义的异常对象
                throw new 自定义异常("原因")


自定义一个异常 要求如果用户的年龄大于200 或者小于 0 抛出异常

public class People {
    private String name;
    private int age;

    public People() {
    }

    public People(String name, int age) throws NoAgeException{
        if(age > 200 || age < 0){
            throw new NoAgeException("年龄是一个非法的值");
        }
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
public class PeopleTest {
    public static void main(String[] args) {
        People people = null;
        try {
            people = new People("天山童姥",18);
            System.out.println(people.toString());
        } catch (NoAgeException e) {
            e.printStackTrace();
        }
    }
}