【Java笔记】20 异常

一、异常概念

程序执行中发生的不正常情况称为异常,语法错误和逻辑错误不是异常

异常分为两大类:

  • Error(错误):虚拟机无法解决的严重问题,如:JVM系统内部错误、资源耗尽等
  • Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理,如:空指针访问,试图读取不存在的文件
    • 运行时异常 程序运行时发生的异常 可以不做处理
    • 编译时异常 编程时由编译器检查出的异常 必须处理
  1. public class Exception01 {
  2. public static void main(String[] args) {
  3. int num1 = 10; int num2 = 0;
  4. // 抛出异常ArithmeticException
  5. // try-catch异常处理机制来解决
  6. // 代码块选中,快捷键ctrl+alt+t,选中try-catch
  7. // 异常处理后,即使出现了异常,程序可以继续运行
  8. try {
  9. int res = num1 / num2;
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. System.out.println("程序继续运行....");
  14. }
  15. }

二、异常体系图

JY66CBJ`4GKU`}G$X237}0L.png

三、五个常见的运行时异常

  1. 空指针异常NullPointerException
    当程序试图在需要对象的地方使用null时,抛出该异常
  1. public class NullPointerException_ {
  2. public static void main(String[] args) {
  3. String name = null;
  4. System.out.println(name.length());
  5. }
  6. }

Exception in thread “main” java.lang.NullPointerException
at java20.exception.NullPointerException.main(NullPointerException_.java:6)

  1. ArithmeticException数学运算异常 如除以0
  2. ArrayIndexOutOfBoundsException数组下标越界异常 索引为负或等于数组大小
  3. ClassCastException试图将对象强制转换为不是实例的子类时
  1. public class Exception02 {
  2. public static void main(String[] args) {
  3. A a = new B(); // 向上转型可以
  4. B b = (B)a; // 向下转型 a本身就指向B 可以
  5. C c = (C)a;
  6. }
  7. }
  8. class A{ }
  9. class B extends A{}
  10. class C extends A{}

Exception in thread “main” java.lang.ClassCastException: java20.exception.B cannot be cast to java20.exception.C
at java20.exception_.Exception02.main(Exception02.java:7)

  1. 数字格式不正确异常 将字符串转成一种数值类型,但该字符串不能转换为适当格式时,抛出
  1. public class NumberFormatException_ {
  2. public static void main(String[] args) {
  3. String name = "aaa";
  4. int num = Integer.parseInt(name);//NumberFormatException
  5. }
  6. }

四、编译异常

在编译期间,就必须处理的异常

常见的编译异常

  • SQLException 操作数据库时,查询表可能发生异常
  • IOException 操作文件时
  • FileNotFoundException 操作不存在的文件时
  • ClassNotFoundException 加载类而类不存在时
  • EOFException 操作文件到达文件末尾
  • IllegalAraguementException 参数异常

五、异常处理

  1. try-catch-finally 捕获异常,自行处理
    try{
    代码可能有异常处
    发生了异常,异常发生后面的代码不会执行,直接进入到catch块
    }catch(Exception e){
    捕获到异常系统将异常封装成Exception对象e,传递给catch
    得到异常对象后,自行处理
    可以有多个catch语句,捕获不同的异常,进行不同的业务处理,父类异常在后,子类异常在前
    }finally{
    不管try代码块是否有异常发生,始终要执行finally
    通常将释放资源的代码放在finally、
    可以没有finally
    }
    根据需要在程序中有多个try-catch块
    try-finally配合使用,没有捕获异常,程序崩溃。应用场景:执行一段代码,不管是否发生异常,都执行某个业务逻辑
    例:如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止
    1. public class TryCatchDetail02 {
    2. public static void main(String[] args) {
    3. //如果try 代码块有可能有多个异常,使用多个catch 分别捕获不同的异常,相应处理
    4. //子类异常在前面,父类异常在后面
    5. try {
    6. Person person = new Person();
    7. person = null;
    8. System.out.println(person.getName());//NullPointerException
    9. int n1 = 10;
    10. int n2 = 0;
    11. int res = n1 / n2;//ArithmeticException
    12. } catch (NullPointerException e) {
    13. e.printStackTrace();
    14. } catch (ArithmeticException e) {
    15. System.out.println(e.getMessage());
    16. }
    17. finally {
    18. }
    19. }
    20. }
    21. class Person{
    22. private String name = "aaa";
    23. public String getName(){
    24. return name;
    25. }
    26. }
    1. public class TryCatchDetail03 {
    2. public static void main(String[] args) {
    3. try {
    4. int n1 = 10;
    5. int n2 = 0;
    6. System.out.println(n1 / n2);
    7. } finally {
    8. System.out.println("执行了finally");
    9. }
    10. System.out.println("程序继续执行..");
    11. }
    12. }

    Exception in thread “main” java.lang.ArithmeticException: / by zero
    at java20.exception_.TryCatchDetail03.main(TryCatchDetail03.java:8)
    执行了finally

    System.out.println(“程序继续执行..”); 这句话不执行

  1. public class TryCatchExercise04 {
  2. public static void main(String[] args) {
  3. Scanner scanner = new Scanner(System.in);
  4. int num = 0;
  5. String inputStr = "";
  6. while (true){
  7. System.out.println("请输入一个整数:");
  8. inputStr = scanner.next();
  9. try {
  10. num = Integer.parseInt(inputStr);
  11. break;
  12. } catch (NumberFormatException e) {
  13. System.out.println("输入的不是一个整数");
  14. }
  15. }
  16. System.out.println("输入的值是" + num);
  17. }
  18. }
  1. throws 抛出异常,交给调用者(方法)处理,最顶级的处理者是JVM
    try-catch和throws二选一,没有显式的选择try-catch和throws ,默认throws
    throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类
  • 注意事项
    编译异常,程序中必须处理
    运行时异常,程序中没有处理,默认就是throws
    子类重写父类的方法时,子类重写的方法,所抛出的异常类型要么和父类的抛出异常一致,要么为父类抛出异常类型的子类型
    throws过程中,如果方法有try-catch,就相当于处理异常,不必再throws

六、自定义异常

  1. 基本概念
    程序中出现某些错误,但错误信息没有再Throwable子类中处理,自己设计异常类
  2. 步骤
    1. 定义类:自定义异常类名 继承Exception或RuntimeException
    2. 如果继承Exception,属于编译异常
    3. 如果继承RuntimeException,属于运行异常,一般都继承RuntimeException

例:年龄要求18-120之间,否则抛出自定义异常

  1. public class CustomException {
  2. public static void main(String[] args){
  3. int age = 180;
  4. if(!(age >= 18 && age <= 120)){
  5. throw new AgeException("年龄不在范围");
  6. }
  7. System.out.println("范围正确");
  8. }
  9. }
  10. // 一般情况下,我们自定义异常是继承RuntimeException
  11. // 即把自定义异常做成运行时异常,好处是,可以使用默认的处理机制
  12. class AgeException extends RuntimeException {
  13. public AgeException(String message) {
  14. super(message);
  15. }
  16. }

七、throw和throws

意义 位置 后面跟的东西
throws 异常处理的一种方式 方法声明处 异常类型
throw 手动生成异常对象的关键字 方法体中 异常对象