Java异常是Java提供的一种识别及响应错误的一致性机制。Java中,所有异常都继承自Throwable类(一个完整可用的类)。整体上分为Error、Exception两个大类,具体结构如下图
一·、Error 类
Error类层次描述了Java程序运行时系统内部错误和资源耗尽错误,一般指与JVM或动态加载等相关的问题。如虚拟机错误、动态链接失败、系统崩溃等。这类错误是我们无法控制的,同时也是挺少见的错误,在编程中不必去处理。可以打开JDK包:java.lang.Error查看所有子类。
二、Exception 类
所有异常的父类,其子类描述了各种可能出现的异常事件。
Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。
通常,Java的异常(包括Exception和Error)分为可查的异常(checked exceptions)和不可查的异常(unchecked exceptions)。
可查异常(编译器要求必须处置的异常):正确的程序在运行中,很容易出现的、情理可容的异常状况。可查异常虽然是异常状况,但在一定程度上它的发生是可以预计的,而且一旦发生这种异常状况,就必须采取某种方式进行处理。
除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。
不可查异常(编译器不要求强制处置的异常):包括运行时异常(RuntimeException与其子类)和错误(Error)。
Exception 这种异常分两大类运行时异常和非运行时异常(编译异常)。程序中应当尽可能去处理这些异常。
运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
非运行时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
三、常见的异常
Exception:异常层次结构的根类
ArithmeticException:算术错误情形,如以0为除数
ClassNotFoundException:不能加载所需的类
ArrayIndexOutOfBoundsException:数组下标越界
NullPointerException:尝试访问null对象成员
InputMismatchException:想得到的类型与输入的数据类型不一致
IllegalArgumentException:方法接收到非法参数
ClassCastException:对象强制类型转换错误
NumberFormatException:数字格式转换错误,如把“ab”转换成数字
四、异常的处理
Java异常处理机制用到的几个关键字:try、catch、finally、throw、throws。
• try -- 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
• catch -- 用于捕获异常。catch用来捕获try语句块中发生的异常。
• finally -- finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
• throw -- 用于抛出异常。
• throws -- 用在方法签名中,用于声明该方法可能抛出的异常。
五、自定义异常
package com.richard.test;
/**
* 自定义异常类
* @author Richard
* @date 2019/4/8 - 9:53
*/
public class MyException extends Exception {
/**
* 错误编码
*/
private String errorCode;
/**
* 是否为属性文件中的key
*/
private boolean propertiesKey = true;
/**
* 构造一个基本异常
* @param msg 信息描述
*/
public MyException(String msg){
super(msg);
}
/**
* 构造一个基本异常
* @param errorCode 错误编码
* @param msg 信息描述
*/
public MyException (String errorCode,String msg){
this(errorCode,msg,true);
}
/**
* 构造一个基本的异常
* @param errorCode 错误编码
* @param msg 信息描述
* @param propertiesKey 是否为属性文件中的key
*/
public MyException (String errorCode,String msg,boolean propertiesKey){
super(msg);
this.setErrorCode(errorCode);
this.setPropertiesKey(propertiesKey);
}
/**
* 构造一个基本异常
* @param errorCode 错误编码
* @param msg 信息描述
* @param cause 根异常类(可以插入任何异常)
*/
public MyException (String errorCode,String msg, Throwable cause){
this(errorCode,msg,cause,true);
}
/**
* 构造一个基本异常
* @param errorCode 错误编码
* @param msg 信息描述
* @param cause 根异常类(可以插入任何异常)
* @param propertiesKey 是否为属性文件中的key
*/
public MyException (String errorCode,String msg,Throwable cause,boolean propertiesKey){
super(msg,cause);
this.setErrorCode(errorCode);
this.setPropertiesKey(propertiesKey);
}
/**
* 构造一个基本异常
* @param msg 信息描述
* @param cause 根根异常类(可以插入任何异常)
*/
public MyException (String msg,Throwable cause){
super(msg,cause);
}
public static void main(String[] args) throws MyException {
int a[] = {1,2,3};
for (int i = 0; i < a.length; i++) {
if (a[i]==1){
throw new MyException("1","第一个异常",new ArithmeticException());
}
/* if(a[i]==2){
throw new MyException("2","第二个异常");
}
else{
throw new MyException("3","第三个异常",true);
}*/
}
}
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;
}
}
实现了很多构造函数,可以根据实际业务需求去抛出相应的自定义异常