一、什么是异常:
异常就是在程序运行或者是编译阶段遇到的一些状况,比如:文件找不到、非法参数等等
它干扰了程序正常执行的流程,Java通过API中Throwable类的众多子类描述各种不同的异常。
因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的 错误条件。
从结构图中可以看出,java中所有的异常都是继承自父类Throwable
二、Throwable
Throwable有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。
(1)Error:
是程序无法处理的错误,Error错误大多数是与代码的编写无关的,这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如:Java虚拟机运行错误(Virtual MachineError)、栈溢出错误…
(2)Exception:
是程序可以处理的异常.
Exception分为两类异常:运行时异常和非运行时异常(编译异常)
非运行时异常(编译器要求必须处理的异常),这类异常是RuntimeException以外的异常,类型上都属于Exception类及其子类,这类异常必须在方法上进行声明抛出,或者就使用try-catch进行捕获处理,否则编译不会通过。
运行时异常(编译器不强制要求处置的异常),这类异常包括RuntimeException及其子类,这类异常java的编译器不会去检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
三、异常的处理机制
(1)异常的默认处理机制:
在一个方法中出现了异常,看当前方法是否存在异常处理代码(try-catch代码),如果有,直接捕获异常并处理,如果没有,则传递给上一级的主调函数(也就是调用我这个方法的函数),上一级也会看自己是否存在异常处理代码,以此类推,最终异常会传递给调用main方法的jvm进行处理。
(2)jvm遇到异常的处理方式:
输出异常信息(异常类型、异常信息、异常位置),终止程序
(3)Throwable的几个常见方法
a:getMessage()
获取异常信息,返回字符串。
b:toString()
获取异常类名和异常信息,返回字符串。
c:printStackTrace()(JVM默认处理方式)
获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
四、自定义异常
(1)书写一个异常类,继承Exception类或者RuntimeException
public class MyException extends Exception{
private int code;
public MyException(String msg,int code){
super(msg);
this.code = code;
}
public MyException(String msg){
this(msg,5);
}
public MyException(){
this("");
}
public void setCode(int code){
this.code = code;
}
public int getCode(){
return this.code;
}
public String toString(){
return super.toString() + ", code=" + code;
}
}
(2)使用自定义异常类
public class MyTest {
private int value;
public void setValue2(int value) throws MyException{//异常声明抛出,抛给调用该方法的方法(用逗号隔开多个Exception)
if(value < -3 || value > 3) {
throw new MyException("input value out of range!",value); //抛出异常对象
}
this.value = value;
}
public void setValue(int value){
try{//异常处理
if(value < -3 || value > 3) {
throw new Exception("input value out of range!");
}
this.value = value;
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args){
MyTest t = new MyTest();
try{//异常处理
t.setValue2(9);
}catch(MyException e){
e.printStackTrace();
System.out.println(e.getCode());
}
}
}
(3)throw和throws的区别:
a.throws:用在方法的后面,用于声明抛出的异常,可以声明抛出多个异常,用逗号隔开
b.throw:用在可能发生该异常的代码中,用于抛出异常对象,
比如说 你写了个除法的方法… chufa(int a, int b)
当b == 0 的时候你可以这样
if(b == 0){
throw new MyException(“除数不能为0”);
}
这样就抛出了你自己的异常来提示错误信息…
五、异常常考面试题:
(1)try—catch—finally结构
try{
可能会出现异常情况的代码
}catch(异常类型 异常参数){
异常处理代码
}catch(异常类型 异常参数){
异常处理代码
}finally{
用于释放资源,在IO流操作和数据库操作中会见到
}
(2)如果try代码块中没有抛出异常,try代码块中语句会顺序执行完,catch代码块内容不会被执行;
(3)如果try代码块中抛出catch代码块所声明的异常类型对象,程序跳过try代码块中接下来代码,直接执行catch代码块中对应内容;
a. 可以存在多个catch代码块,究竟执行哪个,看抛出的异常对象是否是catch代码块中异常类型;
b. 异常只能被一个异常处理器所处理, 不能声明两个异常处理器处理相同类型的异常;
c. 多个catch语句块所声明的异常类型不能越来越小;
(4)finally唯一不执行的情况:
try或catch块中调用了退出虚拟机的方法(即System.exit(-1);)
(5)try-catch中出现return或者throw的情况
当try和catch块中遇到throw语句或者return语句的时候,由于这两个语句会导致该方法立即结束,
所以系统并不会立即执行这两条语句,而是去寻找该异常处理流程中的finally块,
如果有就先执行finally再执行try和catch块中的return、throw语句。
(6)final,finally和finalize的区别
final可以修饰类、方法、变量
finally是try语句中的一个语句体,用来释放资源,不能单独使用
finalize是Object中一个方法,当垃圾回收器回收类对象资源时,对象的垃圾回收器调用该方法。