Java:Exception

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

没什么用的前言

try-catch-finally中哪个部分可以省略

catch和finally可以省略其中的一个,catch和finally不能同时省略,省略了catch块发生异常时就不会捕获异常了,所以不推荐

Error和Exception的区别

在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的。比如: 客户输入数据的格式, 读取文件是否存在, 网络是否始终保持通畅等等。

  • Error: Java虚拟机无法解决的严重问题,常是不可恢复的,比如内存溢出, JVM系统内部错误、 资源耗尽等程序无法处理

  • Exception:表示需要捕获,程序能处理的异常,是一种设计或实现问题。

    • 运行时异常,虚拟机运行程序时可能发生的异常,通常只要程序设计没有问题就不会发生。

      java.lang.RuntimeException类及它的子类都是运行时异常。对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。

    • 编译时异常,编译器要求方法必须捕获或声明抛出可能发生的受检查异常,也就是说编译器在编译时能检查到的异常

常见的异常类

受检查异常主要有

受检查异常说明
ClassNotFoundException没有找到类
IllegalAccessException访问类被拒绝
InstantiationException试图创建抽象类或接口的对象
InterruptedException线程被另一个线程中断
NoSuchFieldException请求的域不存在
NoSuchMethodException请求的方法不存在
ReflectiveOperationException与反射有关的异常的超类
IO异常

运行时异常主要有

运行时异常说明
ArithmeticException算术错误异常,如以零做除数
ArraylndexOutOfBoundException数组索引越界
ArrayStoreException向类型不兼容的数组元素赋值
ClassCastException类型转换异常
IllegalArgumentException使用非法实参调用方法
lIIegalStateException环境或应用程序处于不正确的状态
lIIegalThreadStateException被请求的操作与当前线程状态不兼容
IndexOutOfBoundsException某种类型的索引越界
NullPointerException尝试访问 null 对象成员,空指针异常
NegativeArraySizeException再负数范围内创建的数组
NumberFormatException数字转化格式异常,比如字符串到 float 型数字的转换无效
TypeNotPresentException类型未找到

指针:指针存放的是内存地址

空指针:所以当指针不指向任何内存地址时,就叫做空指针,例如:int[] array = null

**空指针异常:**就是一个指针不指向任何内存地址,但是你还调用他了

int[] array = null; System.out.println(array[0]);

这个时候原本array数组是个空指针,没有创建新的对象,在调用这个数组的时候就会产生空指针异常的错误!

异常处理机制一:try-catch-finally

在编写程序时,经常要在可能出现错误的地方加上检测的代码,如进行x/y运算时,要检测分母为0,数据为空,输入的不是数据而是字符等。过多的if-else分支会导致程序的代码加长、臃肿,可读性差。因此采用异常处理机制。使得程序简洁、优雅, 并易于维护

异常对象的生成

  • 由虚拟机自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出——自动抛出

  • 由开发人员手动创建: Exception exception = new ClassCastException();——创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样。

捕获(catch)异常

如果一个方法内抛出异常, 该异常对象会被抛给调用者方法中处理。
如果异常没有在调用者方法中处理, 它继续被抛给这个调用方法的上层方法
这个过程将一直继续下去, 直到异常被处理。这一过程称为捕获(catch)异常。

在这里插入图片描述

如果一个异常回到main()方法, 并且main()也不处理, 则程序运行终止

异常处理是通过try-catch-finally语句实现的。

  • try

捕获异常的第一步是用try{…}语句块选定捕获异常的范围, 将可能出现异常的代码放在try语句块中。在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配。 一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常处理,一旦处理完成就跳出当前的try-catch结构(在没有写finally的情况下)。继续执行其后的代码

在try结构中声明的变量,不能在try结构外被调用。

  • catch (Exceptiontype e)

在catch语句块中是对异常对象进行处理的代码。 每个try语句块可以伴随一个或多个catch语句, 用于处理可能产生的不同类型的异常对象。catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓,如果异常类型满足子父类的关系,则要求子类一定要声明在父类的上面,否则报错。

  • finally

捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口,使得在控制流转到程序的其它部分以前,能够对程序的状态作统一的管理。finaly中声明的是一定会被执行的代码,即使catch中出现了异常,try中有return语句,catch中有return语句等情况。finally语句和catch语句是任选的。像数据库连接,输入输出流,网络编程socket等资源,JVM是不能自动回收的,我们需要手动的进行资源的释放。此时的资源的释放,就需要声明在finally中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1SHUeuhG-1682473808799)(C:\Users\Joshua.TV\Pictures\webPhoto_Typora\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpYW5nanVueWVz,size_16,color_FFFFFF,t_70-16824250500663.png)]

注意:
如果明确知道产生的是何种异常, 可以用该异常类作为catch的参数;也可以用其父类作为catch的参数。比 如 : 可 以 用ArithmeticException 类 作 为 参 数 的 地 方 , 就 可 以 用RuntimeException类作为参数, 或者用所有异常的父类Exception类作为参数。但不能是与ArithmeticException类无关的异常, 如NullPointerException(catch中的语句将不会执行) 。

使用try-cathch-finally处理编译时异常,使得程序在编译时不在报错,但在运行时,仍有可能报错。相当我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。

try-catch-finally结构可以相互嵌套。

捕获异常的有关信息:
与其它对象一样,可以访问一个异常对象的成员变量或调用它的方法。
getMessage() 获取异常信息,返回字符串
printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7if0Bfx9-1682473808801)(C:\Users\Joshua.TV\Pictures\webPhoto_Typora\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpYW5nanVueWVz,size_16,color_FFFFFF,t_70-16824251258265.png)]

异常处理机制二:throws +异常类型

如果一个方法(中的语句执行时)可能生成某种异常, 但是并不能确定如何处理这种异常, 则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
在方法声明中用throws语句可以声明抛出异常的列表, throws后面的异常类型可以是方法中产生的异常类型, 也可以是它的父类。一旦方法体执行时,出现异常,仍会在异常代码处,生成一个异常类的对象,此对象满足throws后异常类型是,就会被抛出。异常代码后续的代码,就不会执行

    public void method() {
          try {
              test3();//method方法调用,method方法捕获处理
          } catch (FileNotFoundException e) {
              e.printStackTrace();//打印栈轨迹
          } catch (IOException e) {
              e.printStackTrace();
          }
     }
     
     @Test
     public void test3() throws  FileNotFoundException,IOException {
          File file =new File("heool.txt");//new一个文件对象
          FileInputStream fis = new FileInputStream(file);//new一个文件输入流对象
          
          int data = fis.read();//把fis读到的结果返回给data
          while(data != -1) {//只要不等于-1就一直循环,或者说只有等于-1才退出循环
              System.out.println((char)data);//打印data
              data = fis.read();//重新读fis把结果返回给data
          }
          fis.close();//关闭输入流
     }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VelnB709-1682473808801)(C:\Users\Joshua.TV\Pictures\webPhoto_Typora\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpYW5nanVueWVz,size_16,color_FFFFFF,t_70-16824673138777.png)]

重写方法声明抛出异常的原则

重写方法不能抛出比被重写方法范围更大的异常类型(子类方法抛出的异常不能是父类同名方法抛出的父类)。 在多态的情况下,
对methodA()方法的调用-异常的捕获按父类声明的异常处理。

public class A {
public void methodA() throws IOException {
……
} }
public class B1 extends A {
public void methodA() throws FileNotFoundException {//父类A怎么处理的就怎么处理
……
} }
public class B2 extends A {
public void methodA() throws Exception { //报错
……
} }

如何选择try-catch和throws

如果父类中被重写的方法中没有throws方式处理异常,则子类重写的方法中也不能使用throws,意味如果子类重写的方法中有异常,必须使用try-catch。
执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的,我们建议这几个方法使用throws的方式进行处理。而执行的方法a可以考虑使用try-catch

手动抛出异常

java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出, 也可根据需要使用人工创建并抛出。
首先要生成异常类对象, 然后通过throw语句实现抛出操作(提交给Java运行环境)。
IOException e = new IOException();
throw e;
可以抛出的异常必须是Throwable或其子类的实例。 下面的语句在编译时将会产生语法错误:
throw new String(“want to throw”);

public class ExceptionTest3 {
     public static void main(String[] args) {
          try {
              Student stu=new Student();
              stu.register(-1003);//调用了可能抛异常的方法。
              System.out.println(stu);//重写的了tostring,输出的是id=-1003
          } catch (Exception e) {
              System.out.println(e.getMessage());//打印exception的参数,输入的数据不合法
          }
     }
}
class Student{
     private int id;
     public void register(int id) throws Exception {
          if(id>0) {
              this.id =id;
          }else {
              //System.out.println("输入的id不合法");
              //手动抛出异常
              //throw new RuntimeException("你输入的数据不合法");
              throw new Exception("输入的数据不合法");
          }
     }
     @Override//这里重写的是object的tostring方法
     public String toString() {
          return "Student [id=" + id + "]";
     }
}

用户自定义异常类

一般地,用户自定义异常类都是RuntimeException的子类。
自定义异常类要求

  1. 通常需要编写几个重载的构造器
  2. 需要提供全局常量:serialVersionUID
  3. 通过throw抛出。
  4. 最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型。

用户自定义异常类MyException,用于描述数据取值范围错误信息。用户自己的异常类必须继承现有的异常类。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yoCZLIPq-1682473808803)(C:\Users\Joshua.TV\Pictures\webPhoto_Typora\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpYW5nanVueWVz,size_16,color_FFFFFF,t_70-16824674150759.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dlCeXkX1-1682473808804)(C:\Users\Joshua.TV\Pictures\webPhoto_Typora\watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpYW5nanVueWVz,size_16,color_FFFFFF,t_70-168246742445111.png)]

总结

没什么好总结的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值