Java_异常

本文深入解析Java异常处理机制,涵盖异常概念、防御式编程、异常抛出与捕获、异常体系及分类,探讨受查与非受查异常的区别,提供自定义异常实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.异常是什么?

异常指的就是程序在 运行时 出现错误时通知调用者的一种 机制

  • 有些错误是这样的, 例如将 System.out.println 拼写错了, 写成了 system.out.println. 此时编译过程中就会出错, 这是 “编译期” 出错。
  • 而 “运行时” 指的是程序已经编译通过得到 class 文件了, 再由 JVM 执行过程中出现的错误。

异常的种类有很多, 不同种类的异常具有不同的含义, 也有不同的处理方式。

2.防御式编程

异常的核心思想就是 EAFP。

错误在代码中是客观存在的,我们有两种主要的方式:

  • LBYL: Look Before You Leap. 在操作之前就做充分的检查。
  • EAFP: It’s Easier to Ask Forgiveness than Permission. “事后获取原谅比事前获取许可更容易”. 也就是先操作, 遇到问题再处理。

3.抛异常

语法:throw 异常类型的对象

   public static void main(String[] args) {
        System.out.println(divide(3,0));
    }
    public static int divide(int x, int y) {
        if (y == 0) {
            throw new ArithmeticException("抛出除 0 异常");
        }
        return x / y;
    }

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

4.捕获异常

语法:try-catch-finally //若有try,则catch、finally至少要有一个

 try{
    有可能出现异常的语句 ;
 }[catch (异常类型 异常对象) {
 } ... ]
 [finally {
    异常的出口
 }]
  • try 代码块中放的是可能出现异常的代码。
  • catch 代码块中放的是出现异常后的处理行为。
  • finally 代码块中的代码用于处理善后工作(关闭连接、释放资源、释放锁等), 会在最后执行。
  • 其中 catch 和 finally 都可以根据情况选择加或者不加。

4.1try-catch-finally执行逻辑

异常处理流程::
1.程序中先执行 try 里面的代码。
2.如果try中的代码出现异常,就会结束try中的其他代码.检查当前异常和catch中声明的异常类型是否匹配(是声明的异常类型的子类或者类型完全相同)。
3.如果找到匹配的异常类型,这个异常就被当前catch捕获了.就执行catch中的代码。
4.如果没找到匹配的异常类型,这个异常就会沿着调用栈,传递给方法的调用者。
5.无论是否找到匹配类型catch 语句, finally 都-定会在该方法结束前被执行到。
6.如果上层调用者,也没有合适的catch 代码,异常还是要继续传递给调用者。
7.如果一直向 上传递到main方法,都没有合适的catch语句,最终就交给 JVM 来处理。

  try{
       String str = null;
       System.out.println(str.length());
       System.out.println("str.lrngth() 之后的代码"); //异常后面的代码不执行
  }catch (NullPointerException e){
       System.out.println("捕捉到空指针异常");
  }catch (Exception e){
       System.out.println("异常已经捕捉了"); //异常已经被捕捉了 不执行
  }finally {
       System.out.println("无论如何都要执行finally");
       //即使 try 或 catch 中包含 return 语句,finall 依旧会被执行
  }

运行结果:
在这里插入图片描述
注意:
1.如果 try/catch 中有 return,finally 中也有 return ,则原来的 try/catch 中的 return 不执行。
2.如果 try/catch 中有 return,则 finally 中的代码会在 return 之前执行。

  static int fun(){
        try{
            System.out.println("try 里不触发异常代码");
            return 1;
        } catch (NullPointerException e){
            System.out.println("catch 捕捉到异常处理");
            return 2;
        }catch (Exception e){
            System.out.println("异常已经捕捉了"); //不执行
        }finally {
            System.out.println("无论如何都要执行finally");
            return 3;
        }
   }

   //main方法中调用
   System.out.println(fun());

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

  static int  fun2(){
        try{
            System.out.println("try 里不触发异常代码");
            String s = null;
            System.out.println(s.length());
            System.out.println("str.lrngth() 之后的代码");
            return 1;
        } catch (NullPointerException e){
            System.out.println("catch 捕捉到异常处理");
            return 2;
        }catch (Exception e){
            System.out.println("异常已经捕捉了"); 
        }finally {
            System.out.println("无论如何都要执行finally");
        }
        return 3;
  }

   //main方法中调用
   System.out.println(fun());

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

4.2出现异常之后的处理逻辑

1.直接让程序结束:对于致命问题。
2.打印日志:对于普通问题,可以记录一下出现问题的原因 / 代码位置。e.printStackTrace(); // 异常的调用栈,将 JVM 栈里面的方法之间的调用关系打印出来
3.给程序员通知:短信/电话/微信等。

5.异常体系

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

5.1哪些异常需要 catch ?

1)无法恢复的错误,例如:环境整个都出问题了、硬盘坏了、电量不足等——Error,Erro类型一般不会catch(Erroe指的是 Java 运行时内部错误和资源耗尽错误.,应用程序不抛出此类异常)。
2) 程序员导致的错误,例如:BUG等——继承子RuntimException,BUG尽早暴露,一般也不catch。
3)有机会修复的错误,例如:网络慢了、磁盘慢了等——catch并尝试修复。

  • 如果程序正常结束,进程退出码 0 ;如果出现异常结束,此时退出码 非0。

6.定义异常

创建异常类,自定义的异常类如果继承自 Exception ,此时就是一个受查异常;如果继承自 RuntimeException 就是一个非受查异常。

自定义的异常类建议继承自 Exception,毕竟自己创建的异常类,意图是想进行更进一步的处理的. 如果继承自 RuntimeException 就可能最终遗忘对异常进行处理。

7.异常分类

  • 受查异常(checked exception):Exception 类的子类,但不包含RuntimeException 的子类
  • 非受查异常(unchecked exception):Error 类的子类、RuntimeException类的子类。

注意:不要从Error继承非受查异常
在这里插入图片描述

8.为什么java设计时分受查和非受查异常?

答:受查异常——可恢复的异常,必须显示处理(I.使用try catch处理 II.使用 throws 把异常交给发放调用者处理);非受查异常——不用去catch。

9.受查异常在语法上有哪些特殊要求?

答:如果一个方法可能抛出受查类型的异常,则方法声明中必须给出一个异常列表说明。

10.Demo

class CheckedException extends Exception{ //受查异常
}
class CheckedException2 extends Exception{ //受查异常
}
class UnCheckedException extends RuntimeException{ //非受查异常
}
public class ExceptionDemo {
    public static void throwCheckedException() throws CheckedException, CheckedException2{
        if(true){
        throw new CheckedException();
        }else{
            throw new CheckedException2();
        }
    }
    public static void main(String[] args)throws CheckedException, CheckedException2 {
        throwCheckedException(); //传染性强 必须给出异常列表说明
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值