Java|异常处理机制
一、什么是异常
- 异常指程序运行中出现的各种各样的错误,如:文件找不到、网络连接失败、非法参数等。
- 异常有些是用户错误引起的,有些是程序错误引起的,有些是物理错误引起的
- 异常是一个事件,它发生在程序运行期间,中断了正在执行的程序的正常指令流。
二、异常的种类
-
检查性异常(CheckedException)
- 程序员不可预见的
- 典型的如用户输入错误
- 编译时不能忽略
-
运行时异常(RuntimeException)
- 编写代码时不报错,一运行会报错的异常,是可以预见的异常,如代码的一些逻辑错误等。
- 可以通过捕捉处理使程序继续执行,是程序自身可以处理的异常,也称为非致命性异常类。
- 编译时可以被忽略
-
错误(Error)
- Error不是异常!它是由虚拟机生成并抛出的。
- Error及其子类描述Java运行系统中的内部错误以及资源耗尽的错误
- Error是灾难性的致命的错误,是脱离程序员控制的问题,这类的大多数错误与代码编写者执行的操作无关。
- 当出现Error时,JVM一般会选择终止线程。
- 常见的Error如栈溢出等,即使编译也检查不到。
-
注:Exception和Error的区别
- Exception可以通过程序自身捕捉处理,而Error是程序自身无法处理的。
三、异常体系结构
-
Java把异常当作对象处理
- 定义了一个基类java.lang.Throwable作为所有异常的超类。
- 因此,java异常都是Throwable类的实例。
-
异常体系结构层次
四、异常处理机制(捕捉和处理异常)
- 代码示例1
public static void main(String[] args){
int a=1;
int b=0;
//捕捉多个异常,多重捕捉,写多个catch,层次从低到高
//alt+cmd+T
try {//try监控区域(要捕捉异常的代码块)
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace();//打印错误的栈信息
} catch (Error e){
System.out.println("Error");
} finally {//处理善后工作,无论如何都会执行。
System.out.println("finally");
}
}
上述代码我们可以看到
- try至少和一个catch配套
- try语句里的代码块就是需要捕捉异常的代码
- finally语句是可选的,finally语句内的代码块会执行了再报错。常用于I/O流中关闭文件等,是无论如何都要执行的。
- 尽量不要用默认的printStackTrace信息,而是自己去处理异常。
- 被类似的代码块包裹的快捷键是 选中要包裹的代码块,alt+cmd+T
- 多个异常的捕捉要从小到大,不然会遗漏。
-
比如如果第一个catch就捕捉Throwable,第二个catch再写Error,会编译不通过。
-
高层次的Throwable一般放在最后,以免疏漏异常。
-
代码示例2 -> 主动抛出异常(方法内部)
public class Test{
public void test(int a, int b){
if(b == 0)
throw new ArithmeticException(); //主动抛出异常
}
}
public static void main(String[] args){
new Test.test(1,0);
}
-
原本方法中没有方法体,什么也不输出。但经过主动抛出后,会输出异常信息。
-
当我们知道有些情况会导致异常时,可以主动抛出异常。比如示例中除数为0必会报错。
-
代码示例3
//如果在方法中,处理不了异常,就需要在方法上抛出异常。
public class Test{
//假如处理不了异常,将异常抛出给方法调用者
public void test(int a, int b) throws ArithmeticException{
if(b == 0){
throw new ArithmeticException();
}
}
public static void main(String[] args){
//主函数里调用test方法,并给出异常的处理方法。
try{
new Test().test(1,0);
}catch(ArithmeticException e){
e.printStackTrace();
}
}
从上述代码我们可以看到
- 在方法定义时把可预见的异常抛出给了方法调用者
- 方法调用者给出处理异常的方法
五、throw和throws的异同点
- 二者出现位置不一样
- throw语句总是出现在方法体里面,用来抛出一个异常,表示在这个地方就有一个异常出现,程序会在throw后面立即终止,它后面的语句将执行不到。
- throws是出现在方法名的后面,表示当前方法不处理异常,交给方法调用者处理。
- throw只能抛出一个异常,throws可以用逗号分隔抛出多个异常
- throw抛出异常时可以不生命或不捕获,而throws抛出异常时,调用他的方法需要声明异常或用try-catch捕获异常。