Java异常(超详解)

1.异常

1.1异常概念

  • 异常,指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常终止
  • 在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象,Java处理异常的方式是中断处理

1.2异常体系

异常机制其实帮助我们找到程序中的问题,异常的根类是java.lang.Throwable,其中有两个子类,Error和Exception
在这里插入图片描述
Throwable体系:

  • Error :严重的错误,无法通过的错误,只能事先避免,好比绝症
  • Exception:表示异常,异常产生后可以通过代码的方式纠正

Throwable中的常用方法:

  • public void printStackTrace( ):打印异常的详细信息
  • public String getMessage( ):获取发生异常的原因
  • public String toString( ):获取异常的类型和异常描述信息

1.3异常分类

在这里插入图片描述

  • 顶层类 Throwable 派生出两个重要的子类, Error 和 Exception
  • 其中 Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误一旦出现,除了告知用户并使程序终止之外, 再无能无力. 这种情况很少出现.
  • Exception 是我们程序员所使用的异常类的父类.
  • 其中 Exception 有一个子类称为 RuntimeException , 这里面又派生出很多我们常见的异常类
    NullPointerException , IndexOutOfBoundsException 等.

1.4异常的产生过程解析

在这里插入图片描述

2.异常的处理

Java处理异常的5个关键字:try catch finally throw throws

2.1抛出异常throw

2.1.1作用:

  • 可以在指定的方法中抛出指定的异常

2.1.2格式:

  • throw new xxxException(“异常的原因”)

2.1.3注意:

1.throw 关键字必须写在方法的内部
2.throw关键字后面的异常对象必须是Exception或者Exception的子类
3.throw关键字抛出的对象,我们必须要处理

(1)throw后面的是RunTimeException或者是
RunTimeException的子类,我们可以不处理,默认交给JVM来处理
(2)throw后面的是编译期异常(写代码的时候报错),我们必须处理这个异常,要么 try……catch,要么throws

2.1.4代码示例:

    public static void main(String[] args) {
        int [] array = new int [3];
        int e = getElement(array,3);
        System.out.println(e);
    }

    public static int getElement(int [] array,int index){
        if(array == null){
            throw  new NullPointerException("传递数组的值是null");
        }
        if(index < 0 || index >= array.length){
            throw new ArrayIndexOutOfBoundsException("数组索引越界");
        }
        return array[index];
    }

运行结果:
在这里插入图片描述

2.2声明异常throws

2.2.1作用:

  • 当方法内部抛出异常对象的时候,那么我们必须处理这个异常对象,会把异常对象抛出给方法的调用者处理,最终交给JVM处理

2.2.2使用格式:

修饰符 返回值类型 方法名 (参数列表)throws XXXException{
throw new XXXException(“产生原因”);
}

2.2.3注意事项:

  • throws关键字必须写在方法声明处
  • throws关键字后面的异常必须是Exception或者Exception的子类
  • 方法内部如果出现了多个异常对象,那么throws也要抛出多个对象,如果抛出的这个异常对象具有子父类关系,那么直接声明父类异常即可
  • 调用了声明抛出异常的方法,我们就必须处理声明的异常。要么继续使用throws声明抛出,直到抛给JVM;要么使用try……catch来处理这个异常

2.2.4代码示例:

   public static void main(String[] args) throws FileNotFoundException {
       readFile("d:\\a.txt");
   }

   public static  void  readFile(String fileName) throws FileNotFoundException {
       if(!fileName.equals("c:\\a.txt")){
           throw new FileNotFoundException("文件的路径不是c:\\a.txt");
       }
       System.out.println("路径没有问题,读取文件");
   }

运行结果:
在这里插入图片描述

2.3try……catch

2.3.1作用:

  • try中存放可能出现异常的代码,catch中存放异常的处理逻辑

2.3.2使用格式:

try{
可能出现异常的代码;
catch( 定义一个异常的变量,用来接收try中抛出的异常对象){
异常的处理逻辑
}

2.3.3注意事项:

  • try中可能有多个异常对象,那么可以使用多个catch来处理这些对象
  • 如果try中没有产生异常,那么就不会执行catch中的捕获逻辑,但会继续执行try……catch之后的代码
  • 一旦try中出现异常,那么try代码块中的程序就不会继续执行,而是交给catch中的代码执行,catch执行完毕继续往下执行

2.3.4代码示例:

    public static void main(String[] args) {
        try{
            readFile("d:\\a.tx");
        }catch (IOException e){
            System.out.println("文件后缀名不正确");
        }
        System.out.println("后续代码");
    }

    public static  void  readFile(String fileName) throws IOException {
        if(!fileName.equals("d:\\a.txt")){
            throw new FileNotFoundException("文件的后缀不是d:\\a.txt");
        }
        System.out.println("路径没有问题,读取文件");
    }

运行结果:
在这里插入图片描述

2.4finally

2.4.1作用:

无论异常是否发生,最后的finally代码块中的内容一定会被执行到

2.4.2基本格式:

try{
可能出现异常的代码
}catch{
异常的处理逻辑
}finally{
代码块的内容一定会执行
}

2.4.3注意事项:

  • finally不能单独使用,要和try……catch一起使用
  • finally一般用于资源释放

2.4.4代码示例:

    public static void main(String[] args) {
        try {
            readFile("d:\\a.tx");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            System.out.println("资源释放");
        }
    }

    public static  void  readFile(String fileName) throws IOException {
        if(!fileName.equals("d:\\a.txt")){
            throw new FileNotFoundException("文件的后缀不是d:\\a.txt");
        }
        System.out.println("路径没有问题,读取文件");
    }

运行结果:
在这里插入图片描述

2.5异常注意事项

2.5.1多个异常使用捕获如何处理

  • 多个异常分别处理
    代码示例:
    public static void main(String[] args) {
        try{
            int [] arr = {1,2,3};
            System.out.println(arr[3]);
        }catch (ArrayIndexOutOfBoundsException e){
            e.printStackTrace();
        }

        try{
            List<Integer> list = List.of(1,2,3);
            System.out.println(list.get(3));
        }catch (IndexOutOfBoundsException e){
            e.printStackTrace();
        }
        System.out.println("后续代码");
    }

在这里插入图片描述

  • 多个异常一次捕获,多次处理

注意:

一个try中有多个catch,catch里面定义的异常变量,如果有子父类关系,子类必须写在上面

代码示例:

    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){
            e.printStackTrace();
        }catch (IndexOutOfBoundsException e){
            e.printStackTrace();
        }

        System.out.println("后续代码");
    }

运行结果:
在这里插入图片描述

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

        System.out.println("后续代码");
    }

运行结果:
在这里插入图片描述

2.5.2finally中的return语句

如果finally中有return语句,那么永远返回finally中的结果

    public static void main(String[] args) {
        int k = 10;
        int ret = get();
        System.out.println(ret);
    }

    public static int get(){
        int a = 10;
        try{
            return a;
        }catch (Exception e){
            System.out.println(e);
        }finally {
            a = 100;
            return a;
        }
    }

运行结果:
100

2.5.3子父类异常

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

示例:

    public void show01() throws NullPointerException,ClassNotFoundException{

    }

    public void show02() throws IndexOutOfBoundsException{

    }

    public void show03() throws IndexOutOfBoundsException{

    }

    public void show04(){

    }
}

class Zi extends Fu{
    //子类重写父类方法时,抛出和父类一样的异常
    public void show01() throws NullPointerException,ClassNotFoundException{

    }
    //子类重写父类方法时,抛出父类异常的子类
    public void show02() throws ArrayIndexOutOfBoundsException{

    }
    //子类重写父类方法时,可以不抛出异常
    public void show03(){

    }
    //父类没有异常,子类中有异常时,只能用try……catch
    public void show04(){
        try {
            throw new FileNotFoundException();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

3.自定义异常

3.1作用

在开发业务的过程中往往需要自定义异常

3.2格式

public class XXXException extends Exception | RunTimeException{
添加一个空参数的构造方法
添加一个带异常信息的构造方法
}

3.3注意

  • 自定义异常,必须继承Exception或者RunTimeException
  • 继承Exception,那么自定义的异常就是编译期异常,如果方法内部出现了编译期异常,要么throws,要么try……catch
  • 继承RunTimeException,那么自定义的异常为运行期异常,无需处理,交给Java虚拟机来处理(中断处理)

3.4代码示例

public class RegisterException extends Exception{

    public RegisterException(){
        super();
    }

    public RegisterException(String message){
        super(message);
    }
}

public class Demo01RegisterException {
    static  String [] userNames = {"张三","李四","王五"};
    public static void main(String[] args) throws RegisterException {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您的用户名:");
        String str = sc.nextLine();
        checkUserName(str);
    }

    public static  void checkUserName(String username) throws RegisterException {
        for(String name:userNames){
            if(username.equals(name)){
                throw new RegisterException("该用户已被注册");
            }
        }
        System.out.println("注册成功");
    }
}

运行结果:
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值