16 Java 异常的介绍

异常

一、异常

1. 异常的分类

  • java.lang.ThrowableJava语言中所有异常和错误的超类。
    • Exception extends Throwable:编译期异常,进行编译时Java程序出现的问题。
    • RuntimeException extends Exception:运行期异常,Java程序运行过程中出现的问题。
  • 将异常处理掉,程序就可以继续执行。
  • Error extends Throwable:错误,必须修改源代码,程序才能继续运行。

2. 异常的产生过程解析

3. 异常的处理

  • throw关键字

    • 作用:可以使用throw关键字在指定的方法中抛出指定的异常。
    • 使用格式:throw new xxxException("异常产生的原因");
    • 注意:
      • throw关键字必须写在方法的内部。
      • throw关键字后边new的对象必须是Exception或者Exception的子类对象。
      • throw关键字抛出指定的异常对象,我们就必须处理这个异常对象。
        • throw关键字后边创建的是RuntimeException或者是RuntimeException的子类对象,我们可以不处理,默认交给JVM处理(打印异常对象,中断程序)。
        • throw关键字后边创建的是编译异常,我们就必须处理这个异常:throws或者try...catch
    public class Test {
        public static void main(String[] args) {
            int[] arr1 = null;
            //getElement(arr1,0); // NullPointerException: 传入的数组为null
            int[] arr2 = {1,2,3};
            System.out.println(getElement(arr2, 0)); // 1
            getElement(arr2,3); // ArrayIndexOutOfBoundsException: 传入索引错误
        }
    
        private static int getElement(int[] arr, int index) {
            if (arr == null) {
                //运行时异常,默认交给JVM处理
                throw new NullPointerException("传入的数组为null");
            } else if (index < 0 || index > arr.length - 1) {
                //运行时异常,默认交给JVM处理
                throw new ArrayIndexOutOfBoundsException("传入索引错误");
            }
            return arr[index];
        }
    }
    

4. Objets非空判断

  • Objects类中的静态方法:

    • public static <T> T requireNonNull(T obj) :查看指定引用对象是否为null

      • 源码:

        public static <T> T requireNonNull(T obj) {
          if (obj == null) {
            throw new NullPointerException();
          }
          return obj;
        }
        
    • 重载形式:public static <T> T requireNonNull(T obj, String message)

import java.util.Objects;

public class Test {
    public static void main(String[] args) {
        //Objects.requireNonNull(null); // NullPointerException
        Objects.requireNonNull(null,"空指针异常"); // NullPointerException: 空指针异常
    }
}

5. throws关键字:异常处理的第一种方式,交给别人处理

  • 作用:

    • 当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象。
    • 可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理,最终交给JVM处理(中断处理)。
  • 使用格式:在方法声明时使用。

    修饰符 返回值类型 方法名(参数列表) throws AAAException,BBBException...{
      throw new AAAException("产生原因");
      throw new BBBException("产生原因");
      ...
    }
    
  • 注意:

    • throws关键字必须写在方法声明处。
    • throws关键字后边声明的一场必须是Exception或者是Exception子类。
    • 方法内部如果抛出了多个异常对象,那么throws后边必须也声明多个异常。
      • 如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可。
    • 调用了一个声明抛出异常的方法,我们就必须处理声明的异常。
      • 要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM
      • 要么使用try...catch自己处理异常。
public class Test {

    public static void main(String[] args) throws IOException {
        method("/Users/zgl/Desktop/a.txt"); // 读取文件
        //method("/Users/zgl/Desktop/b.txt"); // FileNotFoundException: 没有该文件
        method("a.tx"); // IOException: 文件后缀不是.txt
    }

    public static void method(String str) throws IOException {
        /*if (!str.equals("/Users/zgl/Desktop/a.txt")) {
            throw new FileNotFoundException("没有该文件");
        } else*/ if (!str.endsWith(".txt")) {
            throw new IOException("文件后缀不是.txt");
        }
        System.out.println("读取文件");
    }
}

6. try…catch:处理异常的第二种方式,自己处理异常

  • 格式:

    try{
      可能产生异常的代码
    }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
      异常的处理逻辑,产生异常对象之后怎么处理这个异常
    }
    ...
    catch(异常类名 变量名){
      ...
    }
    
  • 注意:

    • try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象。
    • 如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行try...catch之后的代码。
    • 如果try中没有产生异常,那么就不会执行catch中的异常处理逻辑,执行完毕try中的代码,继续执行try...catch之后的代码。
    import java.io.IOException;
    
    public class Test {
        public static void main(String[] args) {
            try{
                method("a.txt");    // 读取文件  
                method("a.tx");     // catch: 后缀错误
            }catch (IOException e) {
                System.out.println("catch: 后缀错误");
            }
            System.out.println("catch后的后续代码");   // catch后的后续代码
        }
    
        public static void method(String str) throws IOException {
            if (!str.endsWith(".txt")) {
                throw new IOException("后缀错误");
            }
            System.out.println("读取文件");
        }
    
    }
    
    

7. Throwable类中3个异常处理的方法

  • public String getMessage():返回此throwable的简短描述。
  • public String toString():返回此throwable的详细消息字符串。
  • public void printStackTrace()JVM打印异常对象,默认采用此方法,打印的异常信息是最全面的。
import java.io.IOException;

public class Test {

    public static void main(String[] args) {
        try {
            method("a.tx");
        }catch (IOException e) {
            System.out.println(e.getMessage());  // 后缀错误
            System.out.println(e.toString());  // java.io.IOException: 后缀错误
            System.out.println(e); // java.io.IOException: 后缀错误
            /*
              java.io.IOException: 后缀错误
	            at demo05.Test.method(Test.java:20)
	            at demo05.Test.main(Test.java:9)
            */
            e.printStackTrace();  
        }
    }

    public static void method(String str) throws IOException {
        if (!str.endsWith(".txt")) {
            throw new IOException("后缀错误");
        }
        System.out.println("读取文件");
    }
}

8. finally代码块

  • 格式:

    try{
      可能产生异常的代码
    }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
      异常的处理逻辑,产生异常对象之后怎么处理这个异常
    }
    ...
    catch(异常类名 变量名){
      ...
    }finally{
      无论是否出现异常,都会执行
    }
    
  • 注意:

    • finally不能单独使用,必须和try一起使用。
    • finally一般用于资源释放,无论程序是否出现异常,最后都要将资源释放。
    import java.io.IOException;
    
    public class Test {
    
        public static void main(String[] args) {
            try {
                method("a.tx");
            }catch (IOException e) {
                e.printStackTrace();
            }finally {
                System.out.println("finally代码块");
            }
        }
    
        public static void method(String str) throws IOException {
            if (!str.endsWith(".txt")) {
                throw new IOException("后缀错误");
            }
            System.out.println("读取文件");
        }
    }
    

9. 异常注意事项

  • 多异常的捕获处理:

    • 多个异常分别处理

      import java.util.List;
      
      public class Test01 {
          public static void main(String[] args) {
              try {
                  int[] arr = {1,2,3};
                  System.out.println(arr[3]);
              }catch (ArrayIndexOutOfBoundsException e) {
                  System.out.println(e);  // ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
              }
              try {
                  List<Integer> list = List.of(1, 2, 3);
                  System.out.println(list.get(3));
              }catch (IndexOutOfBoundsException e) {
                  System.out.println(e);  // ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
              }
          }
      }
      
    • 多个异常一次捕获,多次处理

      • 注意:catch里边定义的异常变量,如果有子父类关系,那么子类的异常变量必须写在上边,否则就会报错。
      import java.util.List;
      
      public class Test02 {
          public static void main(String[] args) {
              try {
                  /*int[] arr = {1,2,3};
                  System.out.println(arr[3]);*/
                  List<Integer> list = List.of(1, 2, 3);
                  System.out.println(list.get(3));
              }catch (ArrayIndexOutOfBoundsException e) {
                  System.out.println(e);  // ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
              }catch (IndexOutOfBoundsException e) {
                  System.out.println(e);  // ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
              }
          }
      }
      
    • 多个异常一次捕获一次处理

      import java.util.List;
      
      public class Test03 {
              public static void main(String[] args) {
                  try {
                      int[] arr = {1,2,3};
                      System.out.println(arr[3]);
                      List<Integer> list = List.of(1, 2, 3);
                      System.out.println(list.get(3));
                  }catch (Exception e) {
                      System.out.println(e);  // ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
                  }
              }
      }
      
  • finallyreturn语句

    • 如果finally中有return语句,则永远返回的是finally中的结果,需要避免该种情况。
  • 子父类异常

    • 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
    • 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常,此时子类产生异常,只能捕获处理,不能声明抛出。

10. 自定义异常类

  • java提供的异常类,不够我们使用,需要自己定义一些异常类。

  • 格式:

    public class XXXException extends Exception/RuntimeException{
      添加一个空参数的构造方法
      添加一个带异常信息的构造方法
    }
    
  • 注意:

    • 自定义异常类一般都是以Exception结尾,说明该类是一个异常类。
    • 自定义异常类,必须继承Exception或者RuntimeException
      • 继承Exception:那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,使用throws或者使用try...catch
      • 继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给JVM虚拟机处理(中断处理)。
    public class RegisterException extends Exception {
        public RegisterException(){
            super();
        }
        public RegisterException(String str){
            super(str);
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值