1.概述
异常:程序执行中的不正常情况
- Error:JAVA虚拟机不能解决的问题,如JVM内部错误、资源耗尽(栈溢出:StackOverflowError、堆溢出:OOM)。
- Exception:其它因编程错误或偶然的外部因素导致的一般性问题,可以使用针对性代码进行处理。如空指针、读取文件不存在、网络连接中断、数组越界。
异常体系结构:
java.lang.Throwable,包含两个子类:
-
java.lang.Error:一般不编写针对针对性代码处理。
-
jave.lang.Exception:
- 编译时异常(checked):IOException、ClassNotFoundException...
- 运行时异常RuntimeException(unchecked):NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException、NumberFormatException、ArithmeticException、InputMismatchException...
2.异常处理机制一:try-catch-final
Java中提供处理异常的:抓抛模型——“抛“、”抓“
”抛“:程序执行过程中出现异常,就会在异常处生成一个对应异常类的对象,并将此对象抛出。异常后的代码不再执行。
”抓“:异常处理的方法——try-catch-final、throws
try-catch-final的使用
try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//处理异常的方式1
}catch(异常类型2 变量名2){
//处理异常的方式2
}....//可以有多个catch
finally{
//一定会执行的代码
}
注意几点:
- try将可能出现异常的代码包装起来,一旦出现异常就生成一个对应异常类的对象,根据此对象类型到catch中匹配。
- 异常对象匹配到某个catch,就进入这个catch进行异常处理。处理完成就跳处try-catch,继续执行后边的代码(无finally时)
- 其中finally是可选的。
- catch中的异常,子类要声明在父类之前(如NumberFormatException和NullPointerException顺序无所谓,但一定要在Exception之前)
- catch中常用的异常对象处理方式:a. String getMessage() , b. void printStackTrace()
- try结构中定义的变量只能在try内部使用。
- try-catch结构可以嵌套。
关于finally:
- finially中的代码一定会被执行,即使有以下情况:catch中出现异常、try和catch中有return语句。
- 以下内容可以考虑放在finally中:关于数据库连接、IO流、网络编程Socket等JVM不可回收的资源的资源释放。
3.异常处理机制二:throws
使用:方法声明处 throws 异常类型 {方法体}
表示一旦方法体执行出现异常,仍会在代码异常处生成异常类对象,此对象满足throws后的异常类型后就会被抛出。出现异常后的代码也不会执行。
throws只是将异常抛给了方法的调用者,真正处理异常的还是try-catch-finally。
如何选择try-catch-finally和throws类型?
- 父类中被重写的方法没有用throws处理异常,则子类中被重写的方法也不能使用throws。即子类中的被重写方法必须使用try-catch-finally方式处理。
- 执行某方法a时,调用了几个方法b、c、d...,且b,c,d等方法是递进的(b的结果要作为c方法的参数,以此类推)。建议b、c、d等方法用throws处理异常,方法a用try-catch-finally处理异常。
4.手动抛出异常:throw
手动生成一个异常对象,并抛出:throw new 异常类型
public class ExceptionTest {
public static void main(String[] args) {
Student test = new Student();
try{
test.setId(-1);
}catch(Exception e){
System.out.println(e.getMessage());
//只打印:您想赋予的id值非法(<=0)
}
}
}
class Student{
int id;
public void setId(int id) throws Exception {//向调用本方法的地方抛异常
if(id > 0){
this.id = id;
}
else{
throw new RuntimeException("您想赋予的id值非法(<=0)");
//手动生成异常;注意:此处不要new Throwable对象
}
}
}
5.用户自定义异常类
定义方法:
- 继承现有异常类。
- 提供serialVersionUID,用于唯一标识定义的异常类。
- 提供重载的构造器。
//1.继承:这里可以继承 RunTimeException或Exception(此时包含编译时异常)
public class MyException extends RuntimeException {
//2.提供serialVersionUID
static final long serialVersionUID = -7034897421907766939L;
//3.构造器:
public MyException(){}
public MyException(String msg){
super(msg);//相当于getMessage
}
}