定义
如果某个方法不能按照正常的途径完成任务,就可以通过另一种途径退出方法。在这种情况下会抛出一个错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其它代码也无法继续执行,异常处理机制会将代码执行交给异常处理器。
异常分类
定义:Throwable是Java语言中所有异常或错误的超类,下一层分为Error和Exception
Error
定义:是指Java运行时系统的内部错误和资源耗尽错误,运用程序不会抛出该类对象,如果出现了这样的错误,除了告知用户,剩下的就是尽力使程序安全终止。
Exception
有两个分支,一个是运行时异常:RuntimeException;另一个是检查异常:CheckedException
- RuntimeException:程序员错误导致的异常,是那些可能在Java虚拟机正常运行期间抛出的异常的超类
- CheckedException:一般是外部错误,这种错误都发生在编译阶段,Java虚拟机会强制虚拟机去捕获此类异常,程序会要求你将此类异常进行try catch处理。该异常一般包括几个方面
1.试图在文件末尾读取数据 2.试图打开一个错误格式的URL 3.试图根据给定的字符串查询class对象,而这个字符串表示的类不存在
抛出异常的三种方式
throw、throws、系统自动抛异常
throw和throws的区别:
- throws用在函数上,后面跟的是异常类,可以跟多个异常类,表示的也只是可能抛出该异常
示例代码:public static void testThrows() throws NumberFormatException{}
- throw用在函数内,后面跟的是异常对象,执行throw时已经确定抛出的异常了
示例代码:throw new NumberFormatException();
系统自动抛异常
- 定义:当程序语句出现一些逻辑错误、主义错误或者类型转换错误时,系统会自动抛出异常
- 示例:System.out.println( 5 / 0);
throw的使用习惯
- 通常都是try catch形式处理异常的,将可能抛出异常的代码写在try块中,异常抛出写在catch里面,如果是铺货IO输入和输出的异常时要加上finally,用来关闭输入输出流
- try catch finally执行顺序:代码块(try)最先执行,有对应异常则执行catch块代码,最后执行完了try和catch块代码之后才会执行finally中的代码
自定义异常
优点在于:
- 统一项目对外异常展示的方式
- 有时候我们遇到某些校验或者问题时,需要直接结束掉当前的请求,这时便可以通过抛出自定义异常来结束
- 系统中有些代码是符合Java的代码逻辑,但是不符合我们的业务逻辑,自定义异常可以帮我们处理这类问题
- 使用自定义异常继承相关的异常来抛出处理后的异常信息可以隐藏底层的异常,这样更安全,异常信息也更加的直观
麻烦就是,自定义异常需要我们去控制触发机制,增加了代码的开发成本
使用自定义异常原则:
- 所有异常都必须是 Throwable 的子类。
- 如果希望写一个检查性异常类,则需要继承 Exception 类。
- 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
代码示例:
public class MyException extends RuntimeException{
private String errorCode; //错误编码
private boolean propertiesKey; //消息是否为属性中的key
public MyException(String message){
super(message);
}
public MyException(String errorCode, String message, Throwable cause, boolean propertiesKey){
super(message, cause);
this.setErrorCode(errorCode);
this.setPropertiesKey(propertiesKey);
}
public MyException(String errorCode, String message){
this(errorCode, message, true);
}
public MyException(String errorCode, String message, Throwable cause){
this(errorCode, message, cause, true);
}
public MyException(String errorCode, String message, boolean propertiesKey){
super(message);
this.setErrorCode(errorCode);
this.setPropertiesKey(propertiesKey);
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public boolean isPropertiesKey() {
return propertiesKey;
}
public void setPropertiesKey(boolean propertiesKey) {
this.propertiesKey = propertiesKey;
}
}
public class MyExceptionTest {
public static void main(String[] args){
String[] sexs = {"男性", "女性", "中性"};
for(String sex:sexs){
if("中性".equals(sex)){
throw new MyException("10001" ,"随意的性别");
}else{
System.out.println(sex);
}
}
}
}
参考文章:https://www.cnblogs.com/AlanLee/p/6104492.html
栈轨迹(StackTrace)与异常链
异常链:是一种面向对象编程技术,指将捕获的异常包装进一个新的异常中并重新抛出的异常处理方式。
异常的冒泡上传机制:当一个异常对象产生了以后,其会按照调用层次(一般是方法的调用层次)进行冒泡,直到被try-catch处理,或上报至main()方法,由编译器进行提示。
捕获到异常时,往往需要进行一些处理,比较简单直接的方式就是打印异常栈轨迹(StackTrace)。
栈轨迹核心方法:
- printStackTrace()方法:将栈轨迹信息打印到输出台上
- getStackTrace()方法:返回一个栈轨迹元素的数组,遍历栈轨迹数组代码示例
for(StackTraceElement elem : e.getStackTrace()) { System.out.println(elem); }
- fillInStackTrace()方法:保存栈轨迹
栈轨迹展示示例:
java.lang.Exception: 出问题啦!
at TestPrintStackTrace.f(TestPrintStackTrace.java:3)
at TestPrintStackTrace.g(TestPrintStackTrace.java:6)
at TestPrintStackTrace.main(TestPrintStackTrace.java:10)
参考文章:https://blog.csdn.net/u012501054/article/details/80307503
异常使用原则
构造阶段可能会抛出异常,并且要求清理的,使用嵌套try-catch语句,且是在内层try-catch中进行清理(清理的前提是构造完成)
异常类型回答了“什么”被抛出,异常堆栈跟踪回答了“在哪“抛出,异常信息回答了“为什么“会抛出