异常:
在运行期间发生的不正常情况。
在JAVA中用类的形式对异常的情况进行了类的封装。
这些描述不正常情况的类就称为异常类。 异常类就是java通过面向对象的思想将问题封装成了对象。用异常类对问题进行描述,不同的问题用不同的类进行具体的描述,比如,空指针 脚标越界 等等......
以前将正常流程代码和处理异常的代码相结合,现在是将正常流程代码和处理异常的代码分开,这样就提高了阅读性。
体系:
问题很多,对应的异常类就有很多,通过对这些异常类共性的不断向上提取,就形成了异常体系。Throwable。
这个体系有个特点,就是Throwable及其子类都具有可抛性。即被throw throws抛。
Throwable:
分为两大类:
Error(一般不可处理的问题)由JVM抛出的严重性问题,一般不进行针对性处理,而是直接修改程序。已经让虚拟机不正常了,这是错误。
Exception(可处理)
异常的分类:
编译时被检测异常:只要是Exception及其子类,除了RuntimeException及其子类;
这种异常一但出现,就在编译时出现错误,希望能够得到针对性的处理。
编译时不被检测异常(运行时异常):RuntimeException及其子类;该类是JVM正常运行期间抛出的异常超类;
这种异常一但出现,无法让功能继续运行,一般是调用者导致的或者 引发了内部状态的改变导致的,
这种异常一般不处理,直接编译通过,在运行的时候直接让调用者调用的程序停止,让调用者对代码进行修正。
简单示例:
JAVA编译器,一般是先检查语法错误,再检查逻辑错误。
这里脚标越界
1 class Text{ 2 public static void main(String[] args){ 3 int[] a=new int[3]; 4 A Dome=new A(); 5 Dome.show(a, 3); 6 } 7 8 } 9 class A{ 10 void show(int[] a,int b){ 11 System.out.print(a[b]);//throw new ArrayIndexOutOfBoundsException(b); 12 } 13 14 }
实际上在11行会进行对象的封装,然后把问题反馈给调用者(main)
然而main并没有处理的方法他也只能把问题已同样的方法抛给JVM
JVM便会把问题打印在控制台上,让调用者去处理(在以后开发的时候这些异常存储在日志中)。
代码抛出了异常,该代码下面的代码将不会执行,除了finally。
如果异常的代码catch处理了,那么该异常代码下面的代码会继续执行下去。
自定义异常类:
自定义的异常类,要么继承Exception,要么继承RuntimeException;
当继承Exception时,一定要声明异常,否则编译失败,(就好比你有一块变质的面包,你直接给别人,别人吃了GG,所以一定要声明,让别人有处理的办法)
但是如果继承的是RuntimeException的话,可以编译通过。
1 class Text{ 2 public static void main(String[] args) throws FuShuIndextException{ 3 int[] a=new int[3]; 4 Text1 Dome=new Text1(); 5 Dome.show(a, -1); 6 } 7 8 } 9 class Text1{ 10 void show(int[] a,int b) throws FuShuIndextException{ 11 if(b<0){ 12 throw new FuShuIndextException("数组脚标不能为负"); 13 } 14 15 } 16 17 } 18 class FuShuIndextException extends Exception{ 19 FuShuIndextException(String a){ 20 super(a); 21 } 22 }
throw new FuShuIndextException("数组脚标不能为负"); 打印这句话只需要异常类里面有对应的构造函数,该构造函数调用其父类的方法。
在这里我是用了声明(抛出 throws)的方法解决异常,所以异常代码后面的代码将不会不执行到,
但是这个数组脚标不能为负数的异常是可以用catch的解决的,下面我会用catch的方法来处理这个的异常。
声明和捕捉:
处理异常的两个方法。
声明:声明异常的目的就是为了让调用者处理异常,所以如果声明了异常,那么一定要处理。要么throws要么try catch。
捕捉:try(需要被检测异常的代码) catch(处理异常的代码) finally(里面的代码一定会被执行到),即对异常进行针对性的处理。
1.try catch finally
2.try catch(可以多个)没有需要释放的资源
3.try finally异常无法catch处理,但是需要释放资源
1 class Text{ 2 public static void main(String[] args) { 3 int[] a=new int[3]; 4 Text1 Dome=new Text1(); 5 try{ 6 Dome.show(a, -1); 7 } 8 catch(FuShuIndextException e){ 9 // System.out.println(e); 10 // System.out.println(e.toString()); 11 // System.out.println(e.getMessage()); 12 // e.printStackTrace(); 13 14 }finally{ 15 System.out.println("finall中一定会被执行到的代码"); 16 } 17 System.out.println("解决了问题后依然会运行的代码"); 18 19 20 } 21 22 } 23 class Text1{ 24 void show(int[] a,int b) throws FuShuIndextException{ 25 if(b<0){ 26 throw new FuShuIndextException("数组脚标不能为负"); 27 } 28 } 29 30 } 31 class FuShuIndextException extends Exception{ 32 FuShuIndextException(String a){ 33 super(a); 34 } 35 }
第9-12行的代码是打印异常的信息即"数组脚标不能为负"输出为
FuShuIndextException: 数组脚标不能为负
FuShuIndextException: 数组脚标不能为负
数组脚标不能为负
FuShuIndextException: 数组脚标不能为负
at Text1.show(Text.java:26)
at Text.main(Text.java:6)
第9行等价于第10行,它默认的是e.toString
第12行,JVM默认的异常处理机制就是调用了这个方法
异常处理的原则:
1.函数内容如果抛出了需要检测的异常,那么函数上一定要声明或者try catch捕捉否则编译失败
2.如果调用到了声明异常的函数,那么调用者一定要声明或者try catch捕捉否则编译失败
3.能够处理的异常用try catch自己解决,不能处理的异常用throw告诉调用者,让调用者解决
4.一个功能如果抛出了多个异常,那么调用时要有相对应的catch进行针对性的处理。
内部有几个需要被检测的异常,就要有对应的catch来解决异常
但是当多catch出现的时候要注意父类的catch要放在最后面,否则编译失败,因为父类catch下面的catch都变成了废话
异常的注意事项:
子类覆盖父类,就只能抛出父类的异常,或者子类或者子集
父类没有异常,子类绝对不能抛出异常,只能try catch
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?