Java异常和错误
Java异常和错误
java.lang.Throwable类是java中所有异常(Exception)和错误(Error)的超类
异常和错误的区别在于:异常能够被程序本⾝捕获并处理,错误是程序⽆法处理的
异常
Exception异常分为两⼤类
1. 运⾏时异常:都是RuntimeException类及其⼦类异常,如空指针异常,数组越界异常。这些异常是不受检异常,程序中可以选择捕
获处理,也可以不处理。这种异常⼀般是由程序逻辑错误出错引起的,程序应从逻辑⾓度避免此类异常的产⽣。该类异常的特点是java编译器不会去检查他,也就是当程序中可能出现此异常,即使没有try-catch捕获,也没有throw抛出异常,也能够编译通过。2. ⾮运⾏时异常(编译异常):即RuntimeException以外的异常,类型上都属于Exception类及其⼦类。从程序⾓度来说是必须进⾏处理
的异常,如果不处理,程序就不能编译通过。如IOException,SQLException,等和⽤户⾃定义的Exception异常,⼀般情况下不⾃定义检查异常。
JVM检测到异常时会做的两件事情:
1. JVM会根据产⽣异常的原因创建⼀个异常对象,异常对象内包含了异常产⽣的(内容,原因,位置)
2. 在产⽣异常的语句块中如果没有异常处理逻辑,JVM将会把异常对象逐级抛给⽅法的调⽤者,直到到异常处理逻辑,当抛到main⽅
法时,就会交给JVM⾃⼰处理异常。
3. JVM⾃⼰处理异常时,会将异常对象的内容以红⾊字体打印在控制台,并中断当前执⾏的程序
throw 关键字
作⽤:可以在指定的⽅法中抛出指定的异常
使⽤格式:throw new xxxException(“产⽣异常的原因”);
注意:
1. throw 关键字必须写在⽅法内部
2. throw 关键字后边new 的对象只能是Exception或者Exception的⼦类对象
3. throw 关键字抛出的指定异常对象,我们就必须处理这个异常对象
1. 如果抛出的是运⾏时异常,或者运⾏时异常的⼦类对象,我们可以不处理,默认交给JVM虚拟机处理(打印异常对象,中断程序)
2. 如果抛出的是编译异常,就必须处理这个异常,要么throws,要么try catch捕获
⼯作中注意:
1. 必须⾸先对⽅法传递的参数进⾏合法性校验
2. 如果参数不合法,那么我们就必须使⽤抛出异常的⽅式,告知⽅法的调⽤者,传递的参数有问题
实例:
package ption;
/
/实际项⽬中,不要捕获 Java 类库中定义的继承⾃ RuntimeException 的运⾏时异常类,如:IndexOutOfBoundsException
//或NullPointerException,这类异常由程序员预检查
public class ThrowTest {
public static void main(String[] args){
int[] arr ={0,1,2};
int el =getElement(arr,3);
}
public static int getElement(int[] arr,int index){
if(arr == null){
throw new NullPointerException("数组为空数组");
}
if( index <0|| index > arr.length -1){
throw new ArrayIndexOutOfBoundsException("数组越界");
}
int el = arr[index];
return el;
}
}
控制台输出:
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 数组越界
at Element(ThrowTest.java:16)
at ption.ThrowTest.main(ThrowTest.java:6)
简化判断对象是否为null
if(arr == null){
throw new NullPointerException("数组为空数组");
}
//简化写法
throws 关键字
throws关键字:异常处理的第⼀种⽅式,交给调⽤者去处理
作⽤:
当⽅法内部抛出异常的时候,我们就必须处理这个异常对象
jdk怎么使用可以使⽤throws关键字处理对象,会把异常对象声明逐级抛出给⽅法的调⽤者处理(⾃⼰不处理,交给别⼈处理),如果逐级抛出没有调⽤者处理,那么最终将交由JVM处理,中断程序
使⽤格式:在⽅法声明时使⽤
访问修饰符返回值类型⽅法名(参数列表)throws AAAException,BBBException{
throw new AAAException("产⽣原因");
throw new BBBException("产⽣原因");
}
注意:
1. throws 关键字必须写在⽅法声明处
2. throws 关键字后边声明的异常必须是Exception或者是Exception的⼦类
3. ⽅法内部如果抛出了多个异常对象,那么throws 后⾯就必须也声明多个异常
1. 如果抛出的多个对象存在继承关系,那么直接声明⽗类异常即可
4. 调⽤了⼀个声明抛出异常的⽅法,我们就必须处理声明的异常
1. 要么继续使⽤throws声明抛出,交给⽅法的调⽤者处理,或继续抛出最终交给JVM处理
2. 要么try-catch⾃⼰处理异常
try-catch-finally 关键字
try-catch-finally :异常处理的第⼆种⽅式,⾃⼰处理异常
格式:
try{
可能产⽣异常的代码
}catch(定义异常变量,⽤来接收try中抛出的异常对象){
异常的处理逻辑,捕获异常对象后,怎么处理对象
⼀般在⼯作中,会把异常的信息记录到⼀个⽇志中
}finally{
⽆论是否成功都将执⾏的代码块,多⽤于资源释放,如IO流的关闭
可以根据情况决定是否添加此代码块
}
注意:
1. try 中可能抛出多个异常对象,那么就可以⽤多个catch语句来分别处理这些异常对象
2. 如果try 中出现了异常,那么就将执⾏catch中的异常处理逻辑,执⾏完毕catch中的处理逻辑,继续执⾏try-catch之后的代码;如果
try中没有出现异常,那么就不会执⾏catch中的异常处理逻辑,继续执⾏try 语句块中的代码
3. finally中⽆论是否成功都将执⾏,多⽤于资源释放,如IO流的关闭
⾃定义异常
java提供的异常类不够我们使⽤,需要⾃⼰⾃定义⼀些异常类
格式:
public class xxxException extends Exception | RuntimeException {
添加⼀个空参构造
添加⼀个带异常信息的构造⽅法
}
package ption;
//⾃定义异常类
public class RegisterException extends Exception {
//添加⼀个空参构造
public RegisterException(){
}
//添加⼀个带异常的有参构造
/
/查看源码发现,所有的异常类都有⼀个带异常信息的构造⽅法,⽅法内部会调⽤⽗类带异常信息的构造⽅法,让⽗类来处理这个异常信息
public RegisterException(String message){
super(message);
}
}
注意:
1. ⾃定义异常类⼀般都是以Exception做结尾,说明该类是⼀个异常类
2. ⾃定义异常类必须继承Exception或者RuntimeException
1. 继承Exception:⾃定义异常就是⼀个编译器异常,如果⽅法内部抛出了该异常,那么就必须处理这个异常,要么throws,要么
try-catch
2. 继承RuntimeException:⾃定义异常就是⼀个运⾏期异常,⽆需处理,交给虚拟机处理(中断处理)
项⽬中对异常处理的相关约定和准则
1、不要捕获 Java 类库中定义的继承⾃ RuntimeException 的运⾏时异常类,如:IndexOutOfBoundsException / NullPointerException,这类异常由程序员预检查来规避,保证程序健壮性。
正例: if(obj != null) {…}
反例: try { hod() } catch(NullPointerException e){…}
2、异常不要⽤来做流程控制,条件控制,因为异常的处理效率⽐条件分⽀低。这个坑⼤家要注意了。
3、对⼤段代码进⾏ try-catch,这是不负责任的表现。 catch 时请分清稳定代码和⾮稳定代码,稳定代码指的是⽆论如何不会出错的代码。对于⾮稳定代码的 catch 尽可能进⾏区分异常类型,再做对应的异常处理。
4、捕获异常是为了处理它,不要捕获了却什么都不处理⽽抛弃之,如果不想处理它,请将该异常抛给它的调⽤者。最外层的业务使⽤者,必须处理异常,将其转化为⽤户可以理解的内容。
5、有 try 块放到了事务代码中, catch 异常后,如果需要回滚事务,⼀定要注意⼿动回滚事务。
6、finally 块必须对资源对象、流对象进⾏关闭,有异常也要做 try-catch。说明: 如果 JDK7,可以使⽤ try-with-resources ⽅式。
7、不能在 finally 块中使⽤ return, finally 块中的 return 返回后⽅法结束执⾏,不会再执⾏ try 块中的 return 语句。
8、捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的⽗类。说明: 如果预期对⽅抛的是绣球,实际接到的是铅球,就会产⽣意外情况。
9、⽅法的返回值可以为 null,不强制返回空集合,或者空对象等,必须添加注释充分说明什么情况下会返回 null 值。调⽤⽅需要进⾏ null 判断防⽌ NPE 问题。
说明: 本规约明确防⽌ NPE 是调⽤者的责任。即使被调⽤⽅法返回空集合或者空对象,对调⽤者来说,也并⾮⾼枕⽆忧,必须考虑到远程调⽤失败,运⾏时异常等场景返回 null 的情况。
10、在代码中使⽤“抛异常”还是“返回错误码”,对于公司外的 http/api 开放接⼝必须使⽤“错误码”; ⽽应⽤内部推荐异常抛出;跨应⽤间 RPC 调⽤优先考虑使⽤ Result ⽅式,封装 isSuccess、 “错误码”、 “错误简短信息”。
11、定义时区分 unchecked / checked 异常,避免直接使⽤ RuntimeException 抛出,更不允许抛出 Exception 或者 Throwable,应使⽤有业务含义的⾃定义异常。推荐业界已定义过的⾃定义异常,如: DAOException / ServiceException 等。
12、对于运⾏时异常,我们不要⽤try…catch来捕获处理,⽽是在程序开发调试阶段,尽量去避免这种异常,⼀旦发现该异常,正确的做法就会改进程序设计的代码和实现⽅式,修改程序中的错误,从⽽避免这种异常。捕获并处理运⾏时异常是好的解决办法,因为可以通过改进代码实现来避免该种异常的发⽣。对于受检查异常,没说的,⽼⽼实实去按照异常处理的⽅法去处理,要么⽤try…catch捕获并解决,要么⽤throws抛出!对于Error(运⾏时错误),不需要在程序中做任何处理,出现问题后,应该在程序在外的地⽅问题,然后解决。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论