认识异常
异常指的是导致程序中断执行的一种指令流。 程序中有致命性错误和非致命错误(比如除数为0的异常就是非致命错误),如果需要非致命错误出现后,程序依旧可以正常完成,这就需要一个完善的异常处理机制。
处理异常
处理异常有三种格式可以使用: try. .catch、try…catch… finally、try… finally。
public class . JavaDemo {
public static void main(String args[]) {
System. out. println("*****程序开始执行: *****") ;
try {
System. out.println(" *****数学计算:"+(10/0));
} catch (ArithmeticException e) {
System.out.println("产生异常:"+ e) ;//处理异常
e.printStackTrace()//查看完整的异常信息
} finally {
System.out.printtln("不管程序是否出现异常,都执行此处");
}
System. out. println("*****程序执行完毕*****");
}
}
此时,程序出现异常程序依然可以正常完成,如果要想获得完整的异常信息,就可以使用printStackTrace() 实现
处理多个异常
即便有了异常处理语句,但是如果没有进行正确的异常捕获,那么程序也会导致中断(finally的代码依然执行),这个时候就需要使用多个catch去捕获多个异常 。
异常处理流程
注意:当捕获异常的时候,不知道要捕获哪些异常时(不知道会产生什么异常),就可以捕获 (Exception) 异常,来达到捕获所有异常的目的。
try {
… …
} catch (Exception e){
e.printStackTrace() ;
}
原因在于:在程序之中可以处理的异常的最大的类型是Throwable, 而Throwable中提供有两个子类:
- Error:此时程序还未执行出现的错误,开发者无法处理;
- Exception:程序中出现的异常,开发者可以处理,真正在开发之中所需要关注的就是Exception;
异常产生的时候会产生异常的实例化对象,按照对象的引用原则可以自动向父类转型,所以所有的异常类型都可以使用Exception处理
但是,catch(Exception e)描述的错误信息并不明确,并且在进行多个异常捕获的时候要把捕获范围大的放在后面,比如Exception要写在最后的捕获的地方。
throws和throw关键字
throws关键字
如果说现在假设你定义了一个方法,实际上就应该明确的告诉使用者,这个方法可能会产生何种异常,那么此时就可以在方法的声明上使用throws关键字来进行异常类型的标注。
class MyMath {
//这个代码执行的时候可能会产生异常,如果产生异常调用处来处理
public static int div(int x,int y) throws Exception {
return x/y;
}
public class JavaDemo {
public static void main(String args[]) {
try {
System . out . println(MyMath.div(10,2) ;
} catch (Exception e) {
e.printStackTrace() ;
}
}
}
主方法也可以出现异常,主方法亦可以向上抛出,如果主方法继续向上抛出异常,那么就表示此异常将交由JVM负责处理
class MyMath {
//这个代码执行的时候可能会产生异常,如果产生异常调用处处理
public static int div(int x,int y) throws Exception {
return x/y;
}
public class JavaDemo {
public static void main(String args[]) throws Exception {
System . out . println(MyMath.div(10,0) ;
}
}
如果现在所有的程序执行上只要使用了throws 定义的方法都必须要求开发者进行手工处理,那么这个代码的编写就太麻烦了,所以在设计的过程之中,考虑到代码编写的方便,所以提供有一个灵活的可选的异常处理父类“RuntimeException”,这个类异常的子类可以不需要强制性处理。
面试题:请解释RuntimeException与Exception的区别?列出几个常见的RuntimeException
- RuntimeException是Exception的子类;
- RuntimeException标注的异常可以不需要进行强制性处理,而Exception需要
- 常见的RuntimeException异常:NumberFormatException、ClassCastException、NulPointerException ;
throw关键字
此关键字的主要作用在于表示手工进行异常的抛出,也就是说:此时将手工产生一个异常类的实例化对象,并且进行异常抛出处理
public class JavaDemo {
public static void main (String args[]) {
try {
// 异常对象不再是由系统生成的,而是由手工定义的
throw new Exception("自己抛着玩的对象。") ;
} catch (Exception e) {
e. printStackTrace () ;
}
}
}
面试题:请解释throw与throws区别?
- throw:是在代码块中使用的,主要是手工进行异常对象的抛出;。
- throws:是在方法定义上使用的,表示将此方法中可能产生的异常明确告诉给调用处,交由调用处来处理
异常处理标准格式
class MyMath {
//异常交给被调用处处理则一定要在方法上使用throws
public static int div(int x,int y) throws Exception {
int temp=0;.
System. out . println("【START】除法计算开始。") ;
try {
temp =x/y ;
} catch (Exception e) {
throw e;//向上抛异常对象|
} finally {
System. out. println("【END】除法计算结束。");
}
return temp ;
}
}
public class JavaDemo {
public static void main (String args []) {
try {
System . out . println(MyMath.div(10,0)) ;
} catch (Exception e) {
e . printStackTrace() ;
}
}
}
对于此类操作实际上可以简化,省略掉catch与throw的操作。
自定义异常类
在JDK之中提供有大量的异常类型,但是在实际的开发之中可能这些异常类型未必够使用,不可能所有的设计里面都只是抛出Exception,所以这个时候就需要考虑进行自定义异常类。但是对于自定义异常也有两种实现方案:继承Exception和RuntimeException。
class BombException extend$ RuntimeException {
public BombException (String msg) {
super (msg) ;
}
}
class Food {
public static void eat (int num) throws BombException {
if(num>10){
throw new BombException("吃太多了,肚子爆了。") ;
} else {
System. out . println("正常开始吃,不怕吃胖。") ;
}
}
}
public class JavaDemo {
public static void main (String args []) throws Exception {
Food.eat(11) ;
}
}
assert关键字
从JDK 1.4开始追加有一个断言的功能,确定代码执行到某行之后一定是所期待的结果。对于断言而言并不一定是准确的,也有可能出现偏差,但是这种偏差不应该影响程序的正常执行。