java异常
概述
- Throwable是java.lang包中一个专门用来处理异常的类。
- java错误与异常的超类都是
Throwable
,他的两个子类分别为Error
,Exception
Error错误
- 用来处理程序运行环境方面的异常,比如虚拟机报错(OOM),装载错误和连接错误,这类异常主要是和硬件有关的,而不是由程序本身抛出的。
错误信息 | 错误解释 |
---|---|
java.lang.AbstractMethodError | 抽象方法错误 👉当应用试图调用抽象方法时抛出 |
java.lang.AssertionError | 断言错 👉用来指示一个断言失败的情况 |
java.lang.ClassCircularityError | 类循环依赖错误 👉在初始化一个类时,若检测到类之间循环依赖则抛出该异常 |
java.lang.ClassFormatError | 类格式错误 👉当Java虚拟机试图从一个文件中读取Java类,而检测到该文件的内容不符合类的有效格式时抛出 |
java.lang.ExceptionInInitializerError | 初始化程序错误 👉当执行一个类的静态初始化程序的过程中,发生了异常时抛出。静态初始化程序是指直接包含于类中的static语句段 |
java.lang.IllegalAccessError | 违法访问错误 👉当一个应用试图访问、修改某个类的域(Field)或者调用其方法,但是又违反域或方法的可见性声明,则抛出该异常 |
java.lang.IncompatibleClassChangeError | 不兼容的类变化错误 👉当正在执行的方法所依赖的类定义发生了不兼容的改变时,抛出该异常。一般在修改了应用中的某些类的声明定义而没有对整个应用重新编译而直接运行的情况下,容易引发该错误 |
java.lang.InstantiationError | 实例化错误 👉当一个应用试图通过Java的new操作符构造一个抽象类或者接口时抛出该异常 |
java.lang.InternalError | 内部错误 👉用于指示Java虚拟机发生了内部错误 |
java.lang.LinkageError | 链接错误 👉该错误及其所有子类指示某个类依赖于另外一些类,在该类编译之后,被依赖的类改变了其类定义而没有重新编译所有的类 ,进而引发错误的情况 |
java.lang.NoClassDefFoundError | 未找到类定义错误 👉当Java虚拟机或者类装载器试图实例化某个类,而找不到该类 的定义时抛出该错误 |
java.lang.NoSuchFieldError | 域不存在错误 👉当应用试图访问或者修改某类的某个域,而该类的定义中没有该域的定义 时抛出该错误 |
java.lang.NoSuchMethodError | 方法不存在错误 👉当应用试图调用某类的某个方法,而该类的定义中没有该方法的定义时抛出该错误 |
java.lang.OutOfMemoryError | 内存不足错误 👉当可用内存不足以让Java虚拟机分配给一个对象时抛出该错误 |
java.lang.StackOverflowError | 堆栈溢出错误 👉当一个应用递归调用的层次太深 而导致堆栈溢出时抛出该错误 |
java.lang.ThreadDeath | 线程结束 👉当调用Thread类的stop方法 时抛出该错误,用于指示线程结束 |
java.lang.UnknownError | 未知错误 👉用于指示Java虚拟机发生了未知严重错误的情况 |
java.lang.UnsatisfiedLinkError | 未满足的链接错误 👉当Java虚拟机未找到某个类的声明为native方法的本机语言定义时抛出 |
java.lang.VerifyError | 验证错误 👉当验证器检测到某个类文件中存在内部不兼容或者安全问题时抛出该错误 |
Exception异常
- Exception是Throwable的子类,他的子类中有一个名为
RumtimeException(该类异常也称为运行时异常)
,运行时异常也是我们在开发中最常见的异常类型之一,比如空指针异常,数组下标越界等等…
出现RumtimeException一定是程序在正常运行下抛出的。
异常信息 | 异常解释 |
---|---|
java.lang.ArithmeticException | 算术条件异常 👉 示例:整数除零等 |
java.lang.NullPointerException | 空指针异常类 👉String str = null; str.equals(“Exception”); |
java.lang.ClassCastException | 类型强制转换异常 👉 假设有类A和B(A不是B的父类或子类),O是A的实例,那么当强制将O构造为类B的实例时抛出该异常。该异常经常被称为强制类型转换异常 |
java.lang.ArrayIndexOutOfBoundsException | 数组下标越界异常 👉当对数组的索引值为负数或大于等于数组大小时抛出 |
java.lang.ArrayStoreException | 数组存储异常 👉当向数组中存放非数组声明类型对象时抛出 |
java.lang.ClassNotFoundException | 找不到类异常 👉当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常 |
java.lang.CloneNotSupportedException | 不支持克隆异常 👉当没有实现Cloneable接口或者不支持克隆方法时,调用其clone()方法则抛出该异常 |
java.lang.EnumConstantNotPresentException | 枚举常量不存在异常 👉当应用试图通过名称和枚举类型访问一个枚举对象,但该枚举对象并不包含常量时,抛出该异常 |
java.lang.Exception | 根异常 👉用以描述应用程序希望捕获的情况 |
java.lang.IllegalAccessException | 违法的访问异常 👉当应用试图通过反射方式创建某个类的实例、访问该类属性、调用该类方法,而当时又无法访问类的、属性的、方法的或构造方法的定义时抛出该异常 |
java.lang.IllegalMonitorStateException | 违法的监控状态异常 👉当某个线程试图等待一个自己并不拥有的对象(O)的监控器或者通知其他线程等待该对象(O)的监控器时,抛出该异常 |
java.lang.IllegalStateException | 违法的状态异常 👉当在Java环境和应用尚未处于某个方法的合法调用状态,而调用了该方法时,抛出该异常 |
java.lang.IllegalThreadStateException | 违法的线程状态异常 👉当线程尚未处于某个方法的合法调用状态,而调用了该方法时,抛出异常 |
java.lang.InstantiationException | 实例化异常 👉当试图通过newInstance()方法创建某个类的实例,而该类是一个抽象类或接口时,抛出该异常 |
java.lang.InterruptedException | 被中止异常 👉当某个线程处于长时间的等待、休眠或其他暂停状态,而此时其他的线程通过Thread的interrupt方法终止该线程时抛出该异常 |
java.lang.NegativeArraySizeException | 数组大小为负值异常 👉当使用负数大小值创建数组时抛出该异常 |
java.lang.NoSuchFieldException | 属性不存在异常 👉当访问某个类的不存在的属性时抛出该异常 |
java.lang.NoSuchMethodException | 方法不存在异常 👉当访问某个类的不存在的方法时抛出该异常 |
java.lang.NumberFormatException | 数字格式异常 👉当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常 |
java.lang.RuntimeException | 运行时异常 👉是所有Java虚拟机正常操作期间可以被抛出的异常的父类 |
java.lang.SecurityException | 安全异常 👉由安全管理器抛出,用于指示违反安全情况的异常 |
java.lang.TypeNotPresentException | 类型不存在异常 👉当应用试图以某个类型名称的字符串表达方式访问该类型,但是根据给定的名称又找不到该类型是抛出该异常。该异常与 ClassNotFoundException的区别在于该异常是unchecked(不被检查)异常,而ClassNotFoundException 是checked(被检查)异常 |
java.lang.SecurityException | 安全异常 👉由安全管理器抛出,用于指示违反安全情况的异常 |
EOFException | 文件已结束异常 |
FileNotFoundException | 文件未找到异常 |
NumberFormatException | 字符串转换为数字异常 |
SQLException | 操作数据库异常 |
IOException | 输入输出异常 |
处理异常
- try…catch 捕获异常
try{}...catch(异常类名 变量名){}
try{}...catch(异常类名 变量名){}...catch(异常类名 变量名){}
try{}...catch(异常类名 变量名){}...catch(异常类名 变量名){}...finally{}
try{}...finally{}
//JDK1.7针对多个catch进行了优化:
try{}…catch(异常1 | 异常2 | 异常3….变量名){}…finally{}
简单示例
try {
//当觉得某些代码可能出现异常时,就将其放在try的大括号中
String str = null;
str.equals("Exception");
} catch (NullPointerException e) {
//catch是捕获异常,当try中的代码出现异常时,且catch语句中含有该异常或该异常的父类的定义,那么该异常将被catch捕获,进行处理。
System.out.println("NullPointerException");
} catch (Exception ef) {
System.out.println("Exception");
}finally {
//finally语句中的代码一定会执行,通常用于资源关闭,数据库断开等释放资源的动作
//特殊情况:当在执行finally语句前,退出了Java虚拟机,那么finally语句将不会被执行。
System.out.println("finally一定会执行");
}
运行程序后,得到结果:
NullPointerException
finally一定会执行
需要注意的是:
- try语句中的代码越少越好
- 在有多个catch时,要将父异常放在最后面,来捕获你未预判的异常,写在最前面会直接被执行
- 异常1、异常2都是平级关系的异常,若含有字符关系将报错
- throws 声明异常
throws 声明异常代表着被声明了的方法不会去捕获到异常并去处理他,(比如是Service的业务方法)而是让调用他的位置去处理;
public static int method(int a, int b) throws Exception {
int c = a / b;
return c;
}
- throw抛出异常
throw为抛出异常,在代码中throw new ArithmeticException
就可以无中生有,在业务需要的情况下抛出异常;
public static int method(int a, int b) {
int c = 1;
if (c==1) {
throw new ArithmeticException();
}
return c;
}
自定义异常
1.ResultBean 接口统一返回格式
import lombok.*;
import java.io.Serializable;
@Data
@NoArgsConstructor
@Builder(toBuilder = true)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class ResultBean<T> implements Serializable {
private static final long serialVersionUID = 8676131899637805509L;
// 返回编码
private String code;
// 返回信息
private String msg;
// 签名
@Builder.Default
private String sign = "";
// 返回数据封装
@Builder.Default
private T data = (T) "";
}
2.CodeEnum 返回编码和信息
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum CodeEnum {
OK("200", "成功"),
VALUE_NULL("300", "值为空"),
PARAM_NULL("301", "参数为空,处理异常"),
SIGN_ERROR("400", "签名错误"),
NO_LOGIN("401", "未登录"),
SYS_ERROR("500", "系统异常");
private String code;
private String msg;
// 根据code返回msg信息
public String getMsgByCode(String code) {
for (CodeEnum entry : CodeEnum.values()) {
if (Objects.equals(entry.getCode(), code)) {
return entry.getMsg();
}
}
return "";
}
}
3.自定义异常类(集成 java.lang.下的异常)
import lombok.Getter;
import org.springframework.http.HttpStatus;
/**
* 自定义客户异常
*/
@Getter
public class CustomerException extends RuntimeException {
private String code;
public CustomerException(String message, String code) {
super(message);
this.code = code;
}
}
4.方法中抛出异常throw
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
throw new CustomerException("token不存在或已过期", "401");
// return false;
}
5.异常统一拦截
import ...
/**
* 全局异常处理
*
*/
@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(value = Exception.class)
public ResultBean jsonErrorHandler(Exception e) {
ResultBean res = ResultBean.builder().build();
if (e instanceof BusinessException) {
res.setCode(((BusinessException) e).getCode());
res.setMsg(e.getMessage());
} else {
res.setCode(CodeEnum.SYS_ERROR.getCode());
res.setMsg(CodeEnum.SYS_ERROR.getMsg());
}
return res;
}
}
参考文章
Throwable类与异常—LGM_Hakka
Java中常见的异常(Exception)—Mreden
Java中常见的错误有哪些?— _王文波
自定义异常及异常全局处理—齐大圣2012