Java异常体系

Java异常体系层次

在这里插入图片描述
Java中所有的异常都有一个共同的父类Throwable,它有两个重要的子类ErrorException

Error

Error是程序无法处理的错误,编译器不做检查,通常是JVM运行时发生的异常情况

常见的Error
  • NoClassDefFoundError 类未定义错误
  • StackOverflowError 栈溢出错误
  • OutOfMemoryError 内存溢出错误

NoClassDefFoundError的成因可能是

  1. 类加载的class或者jar包不存在
  2. 类文件存在,但是存在不同的域中
  3. 大小写问题,javac编译的时候不区分大小写,很有可能编译出来的class文件就与想要的不一样

StackOverflowError 的成因可能是深递归造成的Java虚拟机栈被耗尽而抛出的错误

Exception

Exception分为RuntimeException以及非RuntimeException,又被称为UnCheckedException 和 CheckedException 即非受检异常和受检异常。

顾名思义,RuntimeException 即Java运行时抛出的异常,编译器无法检查出来,所以被称为非受检异常,发现后可以处理。

受检异常通常是Exception的直接子类,而非受检异常是RuntimeException的子类。

常见的RuntimeException
  • NullpointException 空指针异常
  • ClassCastException 类型强制转换异常
  • IllegalArgumentException 传递非法参数异常
  • IndexOutOfBoundsExcetption 数组下标越界异常
  • NumberFormatException 数字格式错误异常

NumberFormatException 通常发生在String类型转换成int类型的时候发生的异常,可能由于字符串中存在字母,字符,空格等无法转换成数字的就会抛出该异常。

常见的CheckedException
  • ClassNotFoundException 找不到指定的Class的异常
  • IOException IO异常

ClassNotFoundException 发生的场景可以在反射以及ClassLorder类加载的情况下。
比如Class.forName()这个方法的类路径错误,而找不到那个类。

抛出异常的三种方式

  • throw
  • throws
  • 系统自动抛出
throw

throw是在方法的内部声明,明确声明抛出哪一个异常,即在某种情况下必定抛出异常。

public static void testThrow(){
        int a = 1;
        if(a == 1){
            throw new NullPointerException();
        }else {
            a = 2;
        }
    }
    
    public static void main(String[] args) {
        testThrow();
    }

运行结果

Exception in thread "main" java.lang.NullPointerException
	at com.cakemonster.javabasic.throwable.Throw.testThrow(Throw.java:15)
	at com.cakemonster.javabasic.throwable.Throw.main(Throw.java:22)

即在某种情况下一定会抛出异常。

throws

throws 在方法上声明,不确定是否在何时抛出异常,但是会在某种可能情况下抛出异常。

 public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
		MyClassLoader m = new MyClassLoader("C:\\Users\\蜡笔小新\\Desktop\\", "myClassLoader");
        Class c = m.loadClass("Wali");
        System.out.println(c.getClassLoader());
        System.out.println(c.getClassLoader().getParent());
        System.out.println(c.getClassLoader().getParent().getParent());
        System.out.println(c.getClassLoader().getParent().getParent().getParent());
        c.newInstance();
 }

该方法在找不到该class文件的时候就会抛出ClassNotFoundException,但是又不确定是否会找到,就是可能会抛出的异常。

Java异常机制

  • 异常类型规定了什么异常被抛出
  • 异常堆栈跟踪标明了异常在哪里被抛出
  • 异常信息表明为什么会抛出异常

即异常机制解决了 what,where,why的三个问题

try-catch-finally

try、catch 和 finally 代码块共同形成了一张捕获异常的网。首先,try 语句限定可能抛出异常的代码。在该例子中,异常直接放在 catch 代码块或异常处理函数 中。在所有尝试和捕获都完成后,会继续执行 finally 代码块,无论是否发生了异常。捕获到异常时,可以尝试优雅地进行恢复,也可以退出程序(或方法)。

关于衔接catch块

分为两种情况,一种是没有catch块,一种是一个或多个catch块

  • 没有catch块的时候,就一定要跟上一个finally块。
  • 可以拥有多个 catch代码块,但必须采用某种特定方式来搭建它们。如果所有异常都是其他异常的子类,那么子类会按照 catch 代码块的顺序放在父类前面。
@Test
public void exceptionTest() {
  Logger l = Logger.getLogger(Employee.class.getName());
  File file = new File("file.txt");
  BufferedReader bufferedReader = null;
  try {
    bufferedReader = new BufferedReader(new FileReader(file));
    String line = bufferedReader.readLine();
    while (line != null) {
      // Read the file
    }
  } catch (FileNotFoundException e) {
    l.severe(e.getMessage());
  } catch (IOException e) {
    l.severe(e.getMessage());
  } catch (Exception e) {
    l.severe(e.getMessage());
  } finally {
    // Close the reader
  }
}

在这个示例中,FileNotFoundException 是 IOException 的子类,所以它必须放在 IOException catch 代码块的前面。IOException 是 Exception 的子类,所以它必须放在 Exception catch 代码块的前面。

关于finally的一些问题
  • 不管有没有抛出异常,finally中的语句一定会执行
  • 当try-catch中有return语句的时候,finally还是会执行
  • finally在try或者catch的return语句之后执行,就是说当try-catch块执行完return语句之后,并不会马上返回,而是会继续去执行finally中的代码,当执行完finally之后,才会return。
  • finally中最好不要有return语句,这样的话返回出去的就不会是try-catch中的return,而会是finally中的return的内容。

总结,finally块中的代码会在方法返回之前执行,但是在return语句之后执行。

详细可以看这个博客
https://blog.csdn.net/aaoxue/article/details/8535754

在以下4种特殊情况下,finally块不会被执行:

  • 在finally语句块第一行发生了异常。 因为在其他行,finally块还是会得到执行
  • 在前面的代码中用了System.exit(int)已退出程序。 exit是带参函数 ;若该语句在异常语句之后,-finally会执行
  • 程序所在的线程死亡。
  • 关闭CPU。

Throwable的一些常用方法

  1. getMessage() 返回异常发生时的详细信息
  2. toString() 返回异常发生时的简要信息
  3. getLocalizedMessage() 返回异常对象的本地化信息,使用Throwable的子类覆盖这个方法,可以声称本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同
  4. printStackTrace() 在控制台上打印Throwable对象封装的异常信息

脑图

百度脑图

参考资料
Java异常捕获之try-catch-finally-return的执行顺序
JavaGuide
IBM

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值