异常的捕获和处理
异常处理
异常是程序中导致程序中断的一种指令流
没有异常的程序会从头到尾执行完
出现异常默认情况下会进行异常信息打印
如果没有对异常进行正常的处理程序会中断执行
引入异常处理语句完成代码编写
Java中提供了三个核心关键字
try catch finally
try{
//可能出现异常的语句
}catch(异常类型 对象){
//异常处理
}finally{
//不管出现什么异常,都统一使用的处理代码
}
try捕获可能出现的异常代码
如果try中出现了异常
跳转到catch语句中找到匹配的异常类型进行相应的处理
catch可以省略
或者有多个catch
不管程序中是否有一场,最后的出口都是finally
finally可以省略
catch中的参数: 异常类型 e
所有异常类都会提供printStackTrace()方法,打印异常详细信息
对于有些不能够正常处理的代码,就算有finally程序依旧会中断
一旦中断执行,最后的输出语句肯定不会执行,但是finally依旧会执行。
finally一般是迎来进行资源释放的
捕获异常的try可以和多个catch语句使用,可以捕获更多的一场种类
异常处理流程
所有异常类型最高的继承类是Throwable,它包含两个子类
Error :JVM错误,这时程序没有执行,无法处理
Exception:程序运行时产生的异常,用户可以使用异常处理格式处理
-
当程序中出现了异常,JVM会根据异常的类型实例化一个与之匹配的异常类对象
-
产生异常对象后程序会判断当前语句是否存在异常处理,没有异常处理就交给JVM进行默认的异常处理,即输出异常信息,而后结束程序调用
-
如果存在异常捕获操作,由try捕获产生的异常类实例化对象,再与try后的每一个catch进行比较,如果有合适的捕获类型,就是用当前的catch进行异常处理,不匹配则去找下一个catch
-
不管异常是否能匹配成功,都要向后执行,若程序存在finally语句,就执行finally。
finally执行后,看看catch匹配结果来决定如何执行。
程序类比参数传递
所有的异常类型都可以使用父类Exception来捕获
不可以使用Throwable类,因为Error类型的错误也会被捕获
用户处理不了Error,只能处理Exception
实际开发中所有的异常是用Exception还统一处理还是分开处理要看项目的开发标准是否严格
严谨项目会对每种发生的异常进行不同的处理
处理多个异常时,捕获范围小的异常要放在捕获范围更大的异常之前处理
比如处理ArithmeticException要放在Exception之前
因为AE是E的子类,如果把E放在前面,就算发生了AE类型的异常,但是前面的E是一定会把异常处理掉
所以从逻辑上AE就起不到效果,永远不会被执行到
故范围小的要放在范围大的前面
throws关键字
throws关键字主要在方法定义上使用
表示此方法不进行异常处理,而是交给被调用处处理
谁调用就是谁的锅,要将产生的异常处理掉
当调用此方法时必须明确处理其抛出的异常
class MyMath{
public static int div(int x,int y)throws Exception{
//异常抛出,谁想用这段代码谁就来处理自己使用错误产生的异常
return x/y;
}
}
public class Test{
public static void main(String args[]){
try{
//使用时记得给这个代码加上异常处理
System.out.println(MyMath.div(10,2));
}catch(Exception e){
e.printStackTrace();
}
}
}
由于设计方法需要,一定要加上异常处理,因为你不知道别人会用你的代码进行什么神奇操作
主方法上也可以使用throws抛出异常
这个异常会抛给JVM做默认处理,程序中断
实际上不会这么用
throw关键字
之前的异常对象是JVM自动进行实例化操作
用户可以手动抛出一个实例化对象(手工调用异常类)
public class Test{
public static void main(String args[]){
try{
throw new Exception("自定义异常");
}catch(Exception e){
e.printStackTrace();
}
}
}
这里手动实例化了一个Exception异常类对象并throw抛出
这时就应该明确做异常处理
throws和throw的区别
throw是在方法中人为抛出一个必须被处理的异常类对象
throws是在方法声明中使用,表示此方法在调用时必须处理异常
异常处理的标准格式
将代码理解成资源操作
异常处理模板
class Demo{
public static void fun() throws Exception{
//一系列操作
try{
//一系列操作
}catch(Exception e){ //这里的catch可以省略,称其为简化模式,不建议使用
throw e;
}finally{
//一系列操作
}
}
}
public class Test{
public static void main(String args[]){
try{
Demo.fun();
}catch(Exception e){
e.printStackTrace;
}
}
}
\
RuntimeException类
这种异常不会强制要求用户在程序编译去处理异常,用户根据自己需求有选择性的处理异常
如果没有处理就发生了异常,就交给JVM自动处理
Throwable
Exception
RuntimeException
~~~~
将其抛出,不处理也不会有任何编译语法错误,一旦出现异常就交给JVM默认处理
RuntimeException是Exception的子类
Exception定义了必须处理的异常
RumtimeException定义的异常可以选择性进行处理:
NumberFormatException
ClassCastException
NullPointerException
ArithmeticException
ArrayIndexOutOfBoundsException
assert关键字
JDK1.4引入进行断言
断言是指程序执行到某行后,其结果一定是预期结果
java默认不开启断言,想使用断言要使用-ea选项开启
java -ea 包名.类名
使用断言如果和预期不符,就会报错
自定义异常
在自定义类过程中,java自带异常往往不够用,需要自定义异常类
只要继承Exception(强制性异常处理)或者RuntimeException(选择性异常处理)父类即可
class AddException extends Exception{
public AddException(String msg){
super(msg);
}
}
public class Test{
public static void main(String args[]){
int num =20;
try{
if(num>20){
throw new AddException("数值传递过大");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
以后在其他架构中还会遇到更多类似的自定义异常