Java 异常——Exception详解

异常的介绍

异常的概念

异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。

在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理(停止java虚拟机JVM)。

异常的体系

java.lang.Throwable类:是异常和错误的最顶层的父类

  • 异常:在程序出现了异常,是可以解决的,程序解决了异常可以继续执行

    – java.lang.Exception extends Throwable:编译期异常:写代码的时候(编译)出现的异常

    – java.lang.RuntimeException extends Exception:运行期(时)异常:程序运行的时候出现的异常

  • 错误:在程序中出了错误,是不能解决的,必须的修改代码,把错误去掉,才能让程序执行

    – java.lang.Error extends Throwable:错误

异常的产生过程解析

在这里插入图片描述

throw 创建异常抛出

throw关键字(重点)

作用:可以[在方法中]抛出指定的异常对象

格式:

修饰符 返回值类型 方法名(参数列表){throw new Exception("异常信息");throw new RuntimeException("异常信息");throw new XxxxException("异常信息");}

注意:

1,throw关键字必须写在方法中使用

2,throw关键字后边创建的对象,必须是Exception或者RuntimeException或者他们的子类对象

3,抛出了编译期异常,就必须处理这个编译异常

抛出了运行期异常,可以不用处理这个异常,最终交给JVM处理(中断)

异常的处理

throws 抛给调用者处理

异常处理的第一种方式,建议练习的时候使用,工作使用不要使用

作用:

方法的内部抛出了异常对象,是一个编译期异常,就必须的处理这个编译期异常对象。可以使用throws关键字把异常对象抛出给方法的调用者来处理,最终可以抛出给JVM处理:JVM会以红色的字体把异常对象相关的信息打印在控制台,中断当前正在执行的程序

弊端:程序产生异常,抛出异常对象给JVM,JVM终止程序,产生异常之后的代码就执行不到了

格式:

修饰符 返回值类型 方法名(参数列表) throws xxxException,...,yyyException {throw new xxxException("异常信息");
}

注意:

1,throws关键字必须写在方法声明处

2,一般在方法内部抛出了什么异常对象,就使用throws关键字在方法上声明抛出什么异常对象给方法的调用者处理

a.在方法内部抛出了多个异常对象,就需要使用throws关键字在方法上声明多个异常对象

b.在方法内部抛出了多个异常对象,有子父类关系,在方法上声明父类异常即可

3,调用一个使用throws关键字声明抛出异常的方法,就必须的处理这个异常对象

a.可以使用throws关键字继续声明抛出这个异常对象,最终抛出给JVM处理

b.可以使用try…catch自己手动处理异常

try…catch 手动处理

异常处理的第二种方式,自己手动处理异常,建议工作中使用

作用:

方法的内部抛出了异常对象,是一个编译期异常,我们就必须的处理这个编译期异常对象。调用的方法上声明抛出了异常对象,我们需要处理这个异常对象。可以使用try catch 关键字捕获处理异常,自己定义异常的处理方式

好处:处理了异常之后,程序后续如果有代码,可以继续执行

格式:

        try{可能产生异常的代码}catch (定义一个异常相关的变量){ 变量的作用就是用来接收程序产生的异常对象异常的处理逻辑(想怎么写就怎么写)}...catch (定义一个异常相关的变量){ 变量的作用就是用来接收程序产生的异常对象异常的处理逻辑(想怎么写就怎么写)}

注意:

1.try中可能产生什么异常对象,catch中就要定义什么异常变量来接收这个异常对象

2.如果try中产生了异常对象,就会执行catch中异常的处理逻辑,执行完catch中的代码,继续执行try catch后边的代码

3.如果try中没有产生异常对象,就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try catch后边的代码

4.如果try中产生了多个异常对象,就需要定义多个catch来捕获处理这些异常对象

全局统一异常处理

基于异常监听@ControllerAdvice

/**
* 全局异常处理器
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {/*** 异常处理* @param e* @return*/@ResponseBody@ExceptionHandler(value = Exception.class)public DataResult exceptionHandler(Exception e) {log.error("GlobalExceptionHandler.exceptionHandler , 异常信息",e);return DataResult.fail(e.getMessage());}/*** 业务异常* @param e* @return*/@ResponseBody@ExceptionHandler(value = BplCommonException.class)public DataResult bplCommonExceptionHandler(BplCommonException e) {log.warn("",e);return DataResult.fail(e.getMessage());}/*** 处理所有RequestBody注解参数验证异常* @param e* @return*/@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseBodypublic DataResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e){log.warn(e.getMessage());return DataResult.fail(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());}/*** 处理所有RequestParam注解数据验证异常* @param ex* @return*/@ExceptionHandler(BindException.class)public DataResult handleBindException(BindException ex) {FieldError fieldError = ex.getBindingResult().getFieldError();log.warn("必填校验异常:{}({})", fieldError.getDefaultMessage(),fieldError.getField());return DataResult.fail(ex.getBindingResult().getAllErrors().get(0).getDefaultMessage());}
}

finally 关键字

作用:

finally关键字里边定义的代码,无论程序是否有异常,都会执行。工作中一般用于资源释放(IO)

格式:

try{可能产生异常的代码
}catch(定义一个异常相关的变量 ){异常的处理逻辑(想怎么写就怎么写)
}
...
catch(定义一个异常相关的变量 ){异常的处理逻辑(想怎么写就怎么写)
}finally{无论程序是否有异常,都会执行的代码
}

注意:

1,finally不能单独使用,必须和try一起使用

2,如果try中出现了异常,会先执行catch中异常的处理逻辑,再执行finally中定义的代码。执行完毕finally中的代码,会继续执行try catch finally之后的代码

3,如果try没有异常,执行完try中的代码,再执行finally中定义的代码。执行完毕finally中的代码,会继续执行try catch finally之后的代码

Throwable类中定义的异常处理逻辑

仅供参考,我们可以使用,也可以自己定义异常的处理逻辑

Throwable类中成员方法:

// JVM处理异常对象,把异常对象打印在控制台,默认调用的就是此方法
void printStackTrace()
// 返回此 throwable 的简短描述
String getMessage()
// 返回此 throwable 的详细消息字符串
String toString()

Exception类继承了Throwable,所以Exception所有的子类都可以使用这三个方法

注意事项

运行期异常

  • 运行期异常被抛出可以不处理,默认会交给JVM处理==>中断。

    即不捕获(不使用try catch来捕获处理异常)也不声明抛出(不使用throws声明抛出异常对象)

  • 运行时异常,我们处理没有意义,处理了也是为了让后续代码可以继续执行,但是运行时异常本身还是存在的。

    比如如果使用数组,超出了数组索引的使用范围,就算我们使用try catch处理了运行时异常。实际上数组还是越界的,没有从根本上解决问题。这时候我们应该修改代码,不让数组的索引越界

子父类异常的处理

  • 如果父类的方法抛出了多个异常,

    子类重写父类方法时,子类可以抛出和父类方法相同的异常

    子类重写父类方法时,抛出父类异常的子类

    子类重写父类方法时,可以不抛出异常

  • 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常

    若此时子类产生异常,只能捕获处理,不能声明抛出

重点:子类重写父类方法,父类方法异常什么样,子类和父类一样就可以了,无需考虑异常问题

多个异常的捕获处理

  • 多个异常分别处理

    一个异常使用一个try catch处理

  • 多个异常一次捕获,多次处理

    格式:

    try{...
    }catch(xxxException e){...e.printStackTrace();
    }catch(xxxException e){...e.printStackTrace();
    }
    

    好处:

    简化代码,只写一个try就可以了

    每个catch中都可以写不同的异常处理逻辑

    注意:

    一个try多个catch这种写法,catch中定义的异常变量,不能是下边定义异常变量的父类

  • 多个异常一次捕获一次处理

    格式:

  try{...}catch(Exception e){...e.printStackTrace();}

好处:格式简单

弊端:无论try中有多少种异常产生,只能在catch中写一种异常的处理逻辑

自定义异常类

java给我们提供的异常类不够我们使用,就需要我们自己定义一些异常相关的类

注意:

1.自定义异常类名,一般都是以Exception结尾,说明这就是一个异常相关的的类(见名知意)

2.自定义异常类

a.继承Exception:自定义异常就是一个编译期异常

使用:如果在方法中抛出了编译期异常,那么我们就必须的处理这个异常,有两种处理方式

1)使用throws关键字在方法上继续声明抛出这个异常对象,让方法调用者处理,最终抛出给JVM(中断)

2)使用try catch自己捕获处理异常对象

b.继承RuntimeException:自定义异常就是一个运行期(时)异常

使用:如果在方法中抛出了运行期异常,我们无需处理,默认交给JVM处理(中断)

自定义编译异常类

public class BaseException extends Exception{public BaseException() {}public BaseException(String message) {super(message);}
}

自定义运行期异常类

运行期异常类

/*** 自定义通用运行期异常*/
public class BaseRuntimeException extends RuntimeException{static final long serialVersionUID = -3387516993124229952L;private String code;public BaseRuntimeException() {}public BaseRuntimeException(String message) {super(message);}public BaseRuntimeException(String code, String message) {super(message);this.code = code;}public BaseRuntimeException(String message, Throwable e) {super(message, e);}public BaseRuntimeException(Throwable e) {super(e);}public BaseRuntimeException(BaseResponseEnum responseEnum) {this(responseEnum.getCode(), responseEnum.getMsg());}
}

异常信息码枚举类

import org.assertj.core.util.Preconditions;/*** 异常信息码复用枚举类*/
public class BaseResponseEnum {final private String code;final private String msg;public BaseResponseEnum(String code, String msg){Preconditions.checkNotNull(code);Preconditions.checkNotNull(msg);this.code = code;this.msg = msg;}public String getCode() {return code;}public String getMsg() {return msg;}public static final BaseResponseEnum SUCCESS =new BaseResponseEnum("000000", "sucess");public static final BaseResponseEnum FAILURE =new BaseResponseEnum("999999", "系统繁忙,请稍后再试");public static final BaseResponseEnum BUS_CUSTOMER_ERROR =new BaseResponseEnum("910000", "业务处理异常");public static final BaseResponseEnum ILLEGAL_REQUEST =new BaseResponseEnum("920000", "非法请求");
}

拓展

Objects类中requireNonNull方法

java.util.Objects:操作对象的工具类

// 判断传递的对象是否为null
static <T> T requireNonNull(T obj)
static <T> T requireNonNull(T obj, String message)
/*	如果传递的对象是null,方法内部就会抛出空指针异常如果传递的对象不是null,则方法内部会返回这个对象 */// 方法的源码:
public static <T> T requireNonNull(T obj) {if (obj == null){throw new NullPointerException();}return obj;
}public static <T> T requireNonNull(T obj, String message) {if (obj == null){throw new NullPointerException(message);}return obj;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554809.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java中的URL类根据url获取网络文件快速入门Java中的URL(网络编程)

Java中的URL类 远程连接来实现应用。而且&#xff0c;这个平台现在已经可 以对国际互联网以及URL资源进行访问了。Java的URL类可以让访问网络资源就像是访问你本地的文件夹一样方便快捷。我们通过使用Java的URL类 就可以经由URL完成读取和修改数据的操作。 通过一个URL连接&a…

SpringMVC中Controller为什么能够处理并发访问?Springboot中的定时任务是否会发生阻塞?

文章目录SpringMVC中Controller为什么能够处理并发访问&#xff1f;当多个请求同时访问服务器的时候Controller、Service、DAO是线程安全的吗&#xff1f;关于类中的变量Controller、Service、DAO等类都默认为单例模式Controller、Service、DAO等类中的方法当中的并发问题关于D…

Java进阶 - 易错知识点整理

转载&#xff1a;https://blog.csdn.net/qq_33934427/article/details/125903960 文章目录1、JavaEE2、网络基础3、Mysql4、Spring/SpringMVC&#xff08;IOC装配、AOP增强、常用注解&#xff09;5、Spring Boot/Spring Cloud1&#xff09;SpringBoot部分2&#xff09;SpringCl…

MySQL 视图(详解) navicat如何创建视图

文章目录MySQL 视图&#xff08;详解一&#xff0c;视图概念使用视图的原因二&#xff0c;创建视图&#xff08;1&#xff09;基本语法&#xff08;2&#xff09;创建基于单表的视图【实例 1】【实例 2】&#xff08;3&#xff09;创建基于多表的视图【实例 3】&#xff08;4&a…

使用set集合去除重复元素@EqualsAndHashCode注解

如何使用set集合去重 ​ 我们都知道&#xff0c;set集合是无序的&#xff0c;这样也导致set集合里面的元素是不能重复的&#xff0c;因为这一个特性&#xff0c;所以我们经常用set集合进行去重操作&#xff0c;我们下面以一个简单的例子说明set集合是如何进行去重的。 创建去…

缺少构造方法:Cause java.sql.SQLDataException Unsupported conversion from LONG to java.sql.Timestamp

今天遇到了一个奇怪的错误&#xff0c;报错如下图所示&#xff1a; org.springframework.dao.DataIntegrityViolationException: Error attempting to get column question_id from result set. Cause: java.sql.SQLDataException: Unsupported conversion from LONG to java…

SpringBoot瘦身打包部署

一、前言 最近做的项目由于引入第三方库导致在运行mvn clean package 打jar时&#xff0c;编译出来的 Jar 包很大&#xff08;服务器多达500MB&#xff09;。 二、瘦身前的Jar包 SpringBoot编译出来的Jar包中&#xff0c;磁盘占用大的&#xff0c;是一些外部依赖库&#xff…

XShell直接拖拽文件到服务器,不使用Xftp等文件上传工具

很多情况下&#xff0c;我们使用 Xshell 工具时&#xff0c;如果遇到文件的上传和下载会不可避免的要用到另外一个工具 Xftp&#xff0c;但是频繁的使用 Xftp 会比较麻烦&#xff0c;那么有没有一种更加直接简单的方法呢&#xff1f; 当我们所需要上传的文件比较小的时候&…

System.getProperty()方法获取系统变量

今天在阅读JDBC的DriverManager类源码时&#xff0c;看到了这么一句代码&#xff1a; System.getProperty(“jdbc.drivers”)&#xff1b;getProperty()这个方法是获取指定键指示的系统属性的&#xff0c;也就是说上面的代码获取的是jdbc.drivers这个属性。我写了个测试测试输…

局部变量为什么必须赋值才可以使用

在java内存模型中规定&#xff0c;一个新的变量只能在主存中初始化&#xff0c;不允许在工作内存中直接使用一个未被初始化的变量。 工作内存可以理解为局部变量定义的内存区域&#xff0c;也就是线程的工作内存。所谓局部变量就是线程私有的不共享的空间。 类加载准备阶段 类变…

Java 赋值 “=” 讲解

前言 我们从接触java第一天&#xff0c;就是到 是赋值的意思&#xff0c;把等号右边结果的值&#xff0c;赋给等号左边的变量&#xff0c;那具体是怎样赋值呢&#xff1f;你有了解过吗&#xff1f; 1.0版本 大家都知道&#xff0c;java中有 8大基本类型&#xff0c;对于基本…

Linux 系统管理命令:时间、进程、网络、磁盘、关机重启等 top命令用法详解

文章目录系统管理常用命令1. 日期1.1 查看日历: cal1.2 查看/设置时间: date2. 进程2.1 查看进程信息: ps2.2 动态显示进程信息: top2.3 终止进程: kill2.4 服务的管理: service3. 网络3.1 网卡信息查询与配置: ifconfig3.2 检测远程主机连通性: ping3.3 查看网络状态(监听端口…

Java8中计算时间的四种方式及区别Period、Duration、ChronoUnit、Until 时间区间Duration的简单使用

一.简述 在Java8中&#xff0c;我们可以使用以下类来计算日期时间差异&#xff1a; 1.Period 2.Duration 3.ChronoUnit二.Period类 Period类计算只有年、月、日 计算的是LocalDate两个时间间隔的年月日 public static void main(String[] args) {LocalDate startTime Loc…

[JAVA基础] 成员变量和局部变量(一看就懂的总结归纳篇)

引言 成员变量和局部变量在每种编程语言中都有涉及&#xff0c;如果之前了解过其他语言的成员变量或者局部变量&#xff0c;那么在学习java中的成员变量和局部变量时可以看看有那些联系和不同&#xff0c;这一块的东西也不能说难&#xff0c;如果第一次接触可能会感觉有点乱&a…

【Java多线程】内存模型JMM—主内存与工作内存分析

文章目录JAVA内存模型JVM主内存与工作内存描述JVM内存间交互规则JVM先行发生原则内存交互基本操作的 3 个特性原子性(Atomicity)可见性(Visibility)有序性(Ordering)上述内存模型与Java多线程之间的问题JAVA内存模型 共享变量&#xff1a;如果一个变量在多个线程的工作内存中都…

SpringBoot配置MyBatis的sql执行超时时间(mysql)

当某些sql因为不知名原因堵塞时&#xff0c;为了不影响后台服务运行&#xff0c;想要给sql增加执行时间限制&#xff0c;超时后就抛异常&#xff0c;保证后台线程不会因为sql堵塞而堵塞。 方法一 yml全局配置&#xff1a;单数据源可以&#xff0c;多数据源时会失效 方法二 j…

HTTP协议中的302,303状态码

之前也只知道302,303是请求重定向,但是当被问到302,303的具体区别是什么的时候我有点迷,现在就为了加强记忆,来了解下具体情况: 302是http1.0的内容&#xff0c;303是http1.1的内容。301和302本来在规范中是不允许重定向时改变请求方法的&#xff08;将POST改为GET&#xff09…

Spring自带工具类(断言、ObjectUtils、FileCopyUtils、ResourceUtils、StreamUtils、ReflectionUtils、AopUtils、AopCont)

文章目录断言对象、数组、集合文件、资源、IO 流反射、AOP断言 断言是一个逻辑判断&#xff0c;用于检查不应该发生的情况Assert 关键字在 JDK1.4 中引入&#xff0c;可通过 JVM 参数-enableassertions开启SpringBoot 中提供了 Assert 断言工具类&#xff0c;通常用于数据合法…

Arrays.asList踩坑——引发的Exception in thread “main“ java.lang.UnsupportedOperationException

Exception in thread “main” java.lang.UnsupportedOperationException 如果你尝试修改Arrays.asList方法生产的List&#xff0c;那么就会报这个错误 public static void main(String[] args) {Integer[] arr new Integer[]{7,8,9};List<Integer> list Arrays.asLi…

GIS算法:JAVA拓扑套件JTS

常用可以用于GIS数据处理和空间计算的java包有geotool和jts。 相对来说&#xff0c;geotool功能更全面&#xff0c;还可以用于数据转换、瓦片地图发布、栅格影像分析等&#xff0c;jts只能进行基本的数据处理和空间计算。 但大多数情况下jts就完全够用了。 geotool的官网&am…