异常是在运行时代码序列中产生一种异常情况。异常是一个运行时错误。
异常对象
Java异常是一个描述在代码段中发生的异常(出错)情况的对象。当异常情况发生,一个代表该异常的对象被创建并且在导致该错误的方法中被引发。该方法可以选择自己处理异常或传递该异常;
异常也是一种 class ,因此它本身带有类型信息;
异常类型
所有异常类型都是内置类Throwable的子类。Throwable下面的是两个把异常分成两个不同分支的子类。Error和Exception
Error 表⽰系统级的错误, 是 java 运⾏环境内部错误或者硬件问题, 不能指望程序
来处理这样的问题, 除了退出运⾏外别⽆选择, 它是 Java 虚拟机抛出的。Exception 表⽰程序需要捕捉、 需要处理的常, 是由与程序设计的不完善⽽出现的
问题, 程序必须处理的问题。
Exception 又分为:
- 受检异常(checked exception)
当我们希望我们的⽅法调⽤者, 明确的处理⼀些特殊情况的时候, 就应该使⽤受检异常
- 非受检异常( unchecked exception)
⾮受检异常来说, ⼀般是运⾏时异常, 继承⾃RuntimeException。 在编写代码的时候, 不需要显⽰的捕获,但是如果不捕获, 在运⾏期如果发⽣异常就会中断程序的执⾏;这种异常⼀般可以理解为是代码原因导致的。 ⽐如发⽣空指针、 数组越界等。 这些异常都是可以避免的。 也就不需要我们显⽰的进⾏处理。
关键字
Java异常处理通过5个关键字控制:try、catch、throw、throws和 finally。
程序声明了你想要的异常监控包含在一个try块中。
如果在try块中发生异常,它被抛出。你的代码可以捕捉这个异常(用catch)并且用某种合理的方法处理该异常。
系统产生的异常被Java运行时系统自动引发。手动引发一个异常,用关键字throw。
任何被引发方法的异常都必须通过throws子句定义。
任何在方法返回前绝对被执行的代码被放置在finally块中。
一个异常处理块的通常形式如下:
try {
// block of code to monitor for errors
}
catch (ExceptionType1 exOb) {
// exception handler for ExceptionType1
}
catch (ExceptionType2 exOb) {
// exception handler for ExceptionType2
}
// ...
finally {
// block of code to be executed before try block ends
}
在Java中,凡是可能抛出异常的语句,都可以用 try … catch 捕获。把可能发生异常的语句放在 try { … } 中,然后使用 catch 捕获对应的 Exception 及其子类。
可以使用多个 catch 语句,每个 catch 分别捕获对应的 Exception 及其子类。JVM在捕获到异常后,会从上到下匹配 catch 语句,匹配到某个 catch 后,执行 catch 代码块,然后不再继续匹配。多个 catch 语句只有一个能被执行;
当某个方法抛出了异常时,如果当前方法没有捕获异常,异常就会被抛到上层调用方法,直到遇到某个 try … catch 被捕获为止
自定义异常:
⾃定义异常就是开发人员⾃⼰定义的异常,⼀般通过继承 Exception 的⼦类的⽅式实
现。编写⾃定义异常类实际上是继承⼀个 API 标准异常类,⽤新定义的异常处理信息覆盖
原有信息的过程。
一个常见的做法是自定义一个 BaseException 作为“根异常”,然后,派生出各种业务类型的异常。
BaseException 需要从一个适合的 Exception 派生,通常建议从 RuntimeException 派生:
public class BaseException extends RuntimeException {
}
其他业务类型的异常就可以从 BaseException 派生;
抛出异常时,尽量复用JDK已定义的异常类型;
finally 和 return 的执行顺序
如果 try 中有 return 语句, 那么 finally 中的代码还是会执⾏。因为 return 表⽰的是要整个⽅法体返回, 所以,finally 中的语句会在 return 之前执⾏。
但是 return 前执行的 finally 块内,对值类型数据的修改不起作用,但是对引用类型会影响到