一、概述
1.Java程序在执行过程中所发生的异常事件可分为两类:
1⃣️Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError和OOM。一般不编写针对性的代码进行处理
2⃣️Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:空指针访问、试图读取不存在的文件、网络连接中断、数组角标越界等。
2.一般有两种解决方法。
1⃣️一是遇到错误就终止程序的运行。
2⃣️另一种方法是有程序员在编写程序时,就考虑到错误的检测、错误消息的提示,以及错误的处理。
3.捕获错误最理想的是在编译期间,但有但错误只有在运行时才会发生。比如:除数为0、数组下标越界等。
4.异常分类:编译时异常、运行时异常。
二、异常体系结构
1.java.lang.Throwable
(1)java.lang.Error:一般不编写针对性的代码进行处理。
(2)java.lang.Exception:可以进行异常的处理
1⃣️编译时异常(checked)例如:
IOException、FileNotFoundException、ClassNotFoundException
2⃣️运行时异常(unchecked) 例如:
NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException、
NumberFormatException、InputMismatchException、ArithmeticException
三、异常处理方式
1.两种异常处理方法:
1⃣️try-catch-finally
2⃣️throws+异常类型
2.Java提供的异常处理是:抓抛模型。
1⃣️过程一:“抛”:程序在正常执行过程中,一旦出现异常,就会在异常代码处生成一个对应异常的对象。并将此对象抛出。一旦抛出对象以后,其后的代码就不再执行。
2⃣️过程二:“抓”:可以理解为异常的处理方式:try-catch-finally、throws+异常类型。
try-catch-finally详见:
详解try-catch-finally throws+异常类型详见:
详解throws方式 四、重写方法抛出异常的规则
1.子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型。

public class OverrideTest {
    public static void main(String[] args){
        OverrideTest test=new OverrideTest();
        SuperClass s=new SubClass();
        test.display(s);
    }
    public void display(SuperClass s){
        try {
            s.method();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class SuperClass{
    public void method() throws IOException {

    }
}

class SubClass extends SuperClass{
    public void method() throws FileNotFoundException {
        //此处抛出的异常不能大于父类抛出的异常
        //如果大于,父类抛出的异常,当display()方法调用时,display内的try-catch-finally
        //可能无法处理掉异常
    }
}

五、开发中如何选择哪种方式处理异常
1.如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果子类重写的方法中有异常,必须使用try-catch-finally方式处理。
2.执行的方法中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。则建议这几个方法使用throws的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。
六、手动抛出异常
1.手动抛出异常对应于“抓抛模型”的第一个过程:“抓”。
2.关于异常对象的产生:
1⃣️系统自动生成的异常对象。
2⃣️手动生成一个异常的对象,并抛出(throw)。
注意:此处的抛出是throw,不是throws。
throw是手动的产生一个异常对象。
throws是处理异常的一种方法。

public class StudentTest {
    public static void main(String[] args){
        Student s=new Student();
        try {
            s.regist(-1); //此时输入的数据非法
        } catch (Exception e) {
           System.out.println(e.getMessage());
        }
    }
}

class Student{
    int id;
    public void regist(int id) throws Exception{//这里是异常的处理
        if (id>0){
            this.id=id;
        }else{
            //手动的抛出一个异常对象
            throw new RuntimeException("您输入的数据非法");
        }
    }
}

七、如何自定义异常—用户自定义异常类
1.继承于现有的异常结构L:RuntimeException(运行时异常)、Exception(编译时异常)。
2.提供全局常量serialVersionUID,相当于一个对自定义异常类的标识,序列号,版本号。
3.提供重载的构造器。

public class MyException extends RuntimeException {
    static final long serialVersionUID=-7034897190745766939L;

    public MyException(){

    }

    public MyException(String msg){
        super(msg);
    }
}

应用举例:

public class StudentTest {
    public static void main(String[] args){
        Student s=new Student();
        try {
            s.regist(-1); //此时输入的数据非法
        } catch (Exception e) {
           System.out.println(e.getMessage());
        }
    }
}

class Student{
    int id;
    public void regist(int id) throws Exception{//这里是异常的处理
        if (id>0){
            this.id=id;
        }else{
            //手动的抛出一个异常对象
//            throw new RuntimeException("输入的数据非法");
//            throw new Exception("输入的数据非法");
            throw new MyException("不能输入负数");
        }
    }
}

public class MyException extends RuntimeException {
    static final long serialVersionUID=-7034897190745766939L;

    public MyException(){

    }

    public MyException(String msg){
        super(msg);
    }

}

如有不足指处,还望指出!