异常
异常的设计思维:
由于java是纯面向对象语言,因此java将程序中可能出现的问题都映射成了java类
映射的java类最终形成了异常体系
异常体系:
Throwable 继承 object类
Exception:java程序中出现的异常都是Exception类或者是Exception的子类
Error : 程序中出现的错误,例如:服务器宕机,内存溢出
int[] arr ={1,2,3}; int i = method(arr); System.out.println(i);
private static int method(int[] arr){ return arr[5]; //1.此时因为arr中没有索引5 报异常 jvm会默认创建一个new ArrayIndexOutOfBoundsException(5) //2.由于method方法中没有检测到处理该异常对象的代码 此时method() 就会把new ArrayIndexOutOfBoundsException(5) //抛给method()方法调用者(main)方法 }
//3.main方法会接收到这个异常但是没有检测到处理该异常对象代码 //此时main方法会把这个异常对象抛给main方法的调用者 (JVM) //4.JVM接收到这个new ArrayIndexOutOfBoundsException(5) jvm此时会采用默认异常处理方式: //1)打印异常信息和异常追踪信息 //Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: // Index 5 out of bounds for length 3 // at day15.src.Exception.Exception01.method(Exception01.java:10) // at day15.src.Exception.Exception01.main(Exception01.java:6) //2) 打印完立马终止java程序
举例子
method() 相当于是病人
main 相当于医生 无药可救 就会抛给jvm
JVM 太平间
手动创建异常对象
我们可以通过throw 关键字抛出一个异常
格式:throw new 异常类的构造方法;
注意事项
一旦执行throw new异常类的构造方法;语句,该语句下面的代码都不会执行
throw new 异常类的构造方法下面不能有任何语句, 因为永远执行不到
throw new NullPointerException ()空指针异常
throw new ArrayIndexOutOfBoundsException() 索引越界异常
throw后面抛出的异常类 只能是异常体系的一员
-
throws关键字
当方法抛出异常对象,我们为了让调用者知晓这个方法可能有异常抛出
-
编译时异常与运行时异常
异常(Exception) 类
运行时异常: RuntimeException类及RuntimeException类的子类·
编译时异常:非RuntimeException类及其非RuntimeException类 的子类
运行时异常的特点:
运行时异常可处理(throw,throws,try...catch)可不处理
编译时异常如果代码中有异常(throw) 那么需要处理(throw,try...catch)处理。
-
什么时候用运行时异常?
如果程序中出现啊的问题无法在编译时期被检测,而需要在运行时期检测,那么我们就需要使用运行时异常
例如:例如数组索引越界,数组在运行时期才会在堆内存开辟数组,此时才会去找索引,当索引超出边界时候才会报错。
-
什么时候用编译时异常?
如果程序中出现的问题可以在编译时期检测,那么我们可以考虑使用编译时异常
例如:价格和数量一旦有负值,我们就知道计算总价肯定出现问题
-
-
try....catch(){}
try{
检测可能出现异常的代码,一般写可能出现异常的代码
}catch(异常类型 变量名){
捕获异常对象 ,catch 中异常类型定义为try中可能出现的异常类型
//处理异常的代码 sout
}catch(异常类型2 变量名){
}//也可以有无数个catch
注意 :try以外的代码正常运行,异常会在try运行完毕结束
若发现异常 就会对症抛出异常 try中之后的代码不会执行
try{
//try中代码没有抛出异常,那么就会去执行finally中的语句,程序继续向下执行
//第二种可能: try中代码出现了异常,异常下面的代码不在执行(try中的)接着会去找catch处理这个异常,接着执行finally语句执行完之后,程序继续向下执行
}catch(){
}..finally{
//finally跟在最后一个catch的末尾
无论try中是否抛出异常finally中的语句都会被执行
我们一般把资源释放语句放在其中 防止资源无法释放,例如IO流关闭,数据链接关闭
}
try{
}finally{
第一种可能同上
第二种可能: try中的代码出现了异常 此时try下面的语句不在执行(try中) 接着会去执行finally中的语句执行完fianlly中的语句之后 jvm会去处理这个异常,采用默认处理的方式打印异常信息和异常追踪信息最后停止程序
注意 finally中的代码 一定会执行
}
try{
}catch(){
}
-
trycatch使用注意事项:
1如果多个catch中的异常类型没有父子关系,那么多个catch的顺序不影响最终结果
2.如果多个catch中的异常类型有父子关系,那么父类型的catch不能放在子类型的上方
因为无论子类型异常对象,还是父类型异常对象都会被父类型的catch捕获,那么在父类型catch下边的子类型catch将永远执行不到
-
异常在继承中的使用规则
-
编译时异常在继承中的使用规则:
-
如果父类中的方法声明一个异常,那么子类在重写方法的时候可以不声明该异常或者声明该异常或者声明该异常的子类
-
如果父类没有声明异常,子类在重写该方法时也不能声明异常
-
throwable所有异常顶级父类
中的方法:
try { method(0); } catch (IOException e) { // System.out.println("捕获了IO"); String message = e.getMessage(); System.out.println(message); }
public static void method(int a) throws IOException, Exception { if (a==0){ throw new IOException("IO异常"); } if (a==2){ throw new Exception(); } }
e.getMessage
返回异常对象中封装的异常信息
void printStackTrace()
打印的是异常信息和异常追踪信息 ;相当于默认异常
自定义异常
将AgeException继承Exception代表这个自定义异常为编译时异常
如果继承Exception代表这个自定义异常为编译时异常
如果继承RuntimeException那么这个异常为运行时异常
自定义异常时可以创建构造方法进行传参 。。。
class 类名 extends Exception 或者 RuntimeException{
public 类名(){
super()
}
public 类名(String message){
super(message);
}