【年薪百万之IT界大神成长之路】JAVA 中的异常处理,阅后即焚!!!

2024-03-15 22:30

本文主要是介绍【年薪百万之IT界大神成长之路】JAVA 中的异常处理,阅后即焚!!!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 
愿你如阳光,明媚不忧伤。

目録

    • 1. 异常定义
    • 2. 异常类型
    • 3. 异常方法
    • 4. 异常关键字
    • 5. 内置异常
    • 6. 简单的自定义异常
    • 7. 高级的自定义异常
  • 【每日一面】
          • try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?在finally中return好吗?

 


1. 异常定义

Exception 异常指的是在程序运行过程中发生的异常事件(编译时产生的不是异常,而是错误),通常是由外部问题(如硬件错误、输入错误)所导致的。它阻止了程序按照程序员的预期正常执行。在Java等面向对象的编程语言中异常属于对象

在这里插入图片描述

 


2. 异常类型

Throwable类包括了Error类和Exception类,异常类有两个主要的子类:IOException 类和 RuntimeException 类。

三种类型的异常:

  1. 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
  2. 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略
  3. 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

可以看到 Java 语言定义了很多的异常类在 java.lang 标准包中。实在是太多了,整理不过来,具体遇到时再具体分析。

在这里插入图片描述

 


3. 异常方法

下面的列表是 Throwable 类的主要( public )方法:

方法说明
Throwable()构建一个空的 Throwable ,随后可被 initCause 初始化
Throwable(String message)构建一个带有详细信息的 Throwable ,随后可被 initCause 初始化
Throwable(String message, Throwable cause)构建一个带有详细信息和导致原因的 Throwable
Throwable(Throwable cause)构建一个带有导致原因的 Throwable
final synchronized void addSuppressed(Throwable exception)记录被抑制的异常(finally语句块抛出异常,try语句块中的异常会丢失)
synchronized Throwable fillInStackTrace()清空原来的栈内的trace信息,然后在当前的调用位置处重新建立trace信息
synchronized Throwable getCause()返回一个Throwable 对象异常的导致原因
String getLocalizedMessage()返回关于发生异常的本地化详细信息
String getMessage()返回关于发生异常的详细信息
StackTraceElement[] getStackTrace()返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底
final synchronized Throwable[] getSuppressed()获取被抑制的异常
synchronized Throwable initCause(Throwable cause)初始化导致原因,最多可调用一次
void printStackTrace()打印toString()结果和栈层次到System.err,即错误输出流
void printStackTrace(PrintStream s)打印toString()结果和栈层次到标准错误流
void printStackTrace(PrintWriter s)打印toString()结果和栈层次到指定文件
void setStackTrace(StackTraceElement[] stackTrace)设置将返回的堆栈跟踪元素,高级系统使用
String toString()返回 Throwable 的字符串表示形式

 


4. 异常关键字

finally语句块总是会被执行。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则不会跳回执行,直接停止。
主方法上也可以使用throws抛出。如果在主方法上使用了throws抛出,就表示在主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会导致程序中断执行。

关键字说明
try用于监听异常
catch用于捕获异常
finally用于回收在try块里打开的资源(数据库连接,网络连接,磁盘文件等)
throw用于抛出异常
throws用在方法签名中,用于声明该方法可能抛出的异常

 


5. 内置异常

  • java.lang.ArithmeticException
    算数异常,例如除数不能为0
package com.ITGodRoad.exception;public class ExceptionDemo {public static void main(String[] args) {int a = 5;int b = 0;System.out.println(a / b);}
}-----------------------------------------------------------------
・【运行结果】
Exception in thread "main" java.lang.ArithmeticException: / by zeroat com.ITGodRoad.exception.ExceptionDemo.main(ExceptionDemo.java:7)

Eclipse 中异常快捷键:Alt+Shift+Z

现在我们用try-catch监听并捕获异常

public class ExceptionDemo {public static void main(String[] args) {int a = 5;int b = 0;try {System.out.println(a / b);} catch (ArithmeticException e) {System.out.println("除数不能为0");e.printStackTrace();}}
}-----------------------------------------------------------------
・【运行结果】
除数不能为0
java.lang.ArithmeticException: / by zeroat com.ITGodRoad.exception.ExceptionDemo.main(ExceptionDemo.java:8)

coverage 代码覆盖率 → 无论是否发生异常,finally 代码块中的代码总会被执行。
绿色:代码被执行过
黄色:代码部分被执行过
红色:代码没有被执行过

在这里插入图片描述
throw 主动抛出异常,可以看到虽然捕获的是 ArithmeticException 算数异常,但是控制台信息打印的是我们主动抛出的 RuntimeException 运行时异常。

public class ExceptionDemo {public static void main(String[] args) {int a = 5;int b = 0;try {System.out.println(a / b);} catch (ArithmeticException e) {throw new RuntimeException();} finally {System.out.println("这是一个有趣的世界!");}}
}-----------------------------------------------------------------
・【运行结果】
这是一个有趣的世界!
Exception in thread "main" java.lang.RuntimeExceptionat com.ITGodRoad.exception.ExceptionDemo.main(ExceptionDemo.java:10)

throws 向上抛出异常,用在函数上,声明该函数的功能可能会出现问题,将异常抛出,使问题暴露出来,用于处理。可以抛给虚拟机处理,或者使用 try…catch… 进行处理。虚拟机的处理方式,就是将异常打印出来,并且将在异常处的代码终止

public class ExceptionDemo {public static void main(String[] args) {int a = 5;int b = 0;System.out.println(devision(a, b));}public static int devision(int a, int b) throws ArithmeticException {return a / b;}
}-----------------------------------------------------------------
・【运行结果】
Exception in thread "main" java.lang.ArithmeticException: / by zeroat com.ITGodRoad.exception.ExceptionDemo.devision(ExceptionDemo.java:11)at com.ITGodRoad.exception.ExceptionDemo.main(ExceptionDemo.java:7)

 


6. 简单的自定义异常

在 Java 中你可以自定义异常。如果要自定义异常类,扩展Exception类即可,这样的自定义异常都属于检查异常(checked exception),编译时要求进行 try-catch 处理。如果要自定义非检查异常,则扩展RuntimeException。

按照国际惯例,自定义的异常应该总是包含如下的构造函数:

  1. 一个无参构造函数
  2. 一个带有String参数的构造函数,并传递给父类的构造函数。
  3. 一个带有String参数和Throwable参数,并都传递给父类构造函数
  4. 一个带有Throwable 参数的构造函数,并传递给父类的构造函数。

Alt+shift+S 选择从父类生成构造器即可自动生成上面的构造函数

package com.ITGodRoad.exception;public class ExceptionDemo {public static void main(String[] args) {int a = 5;int b = 0;int result = 0;try {result = devision(a, b);} catch (MyCompileException e) {e.printStackTrace();}System.out.println("程序还可以继续运行,result:" + result);System.out.println("****************************************");updatePassword("123456");}
-----------------------------------------------------------------public static int devision(int a, int b) throws MyCompileException {if (b == 0) {throw new MyCompileException("除数不能为0");}return a / b;}
-----------------------------------------------------------------public static String updatePassword(String password) {if (password.equals("123456")) {throw new MyRuntimeException("密码不能过于简单");}return password;}
}
-----------------------------------------------------------------
class MyCompileException extends Exception {/****/private static final long serialVersionUID = 1L;public MyCompileException() {super();// TODO Auto-generated constructor stub}public MyCompileException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);// TODO Auto-generated constructor stub}public MyCompileException(String message, Throwable cause) {super(message, cause);// TODO Auto-generated constructor stub}public MyCompileException(String message) {super(message);// TODO Auto-generated constructor stub}public MyCompileException(Throwable cause) {super(cause);// TODO Auto-generated constructor stub}}
-----------------------------------------------------------------
class MyRuntimeException extends RuntimeException {/****/private static final long serialVersionUID = 1L;public MyRuntimeException() {super();// TODO Auto-generated constructor stub}public MyRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);// TODO Auto-generated constructor stub}public MyRuntimeException(String message, Throwable cause) {super(message, cause);// TODO Auto-generated constructor stub}public MyRuntimeException(String message) {super(message);// TODO Auto-generated constructor stub}public MyRuntimeException(Throwable cause) {super(cause);// TODO Auto-generated constructor stub}}-----------------------------------------------------------------
・【运行结果】
com.ITGodRoad.exception.MyCompileException: 除数不能为0at com.ITGodRoad.exception.ExceptionDemo.devision(ExceptionDemo.java:23)at com.ITGodRoad.exception.ExceptionDemo.main(ExceptionDemo.java:10)
程序还可以继续运行,result:0
****************************************
Exception in thread "main" com.ITGodRoad.exception.MyRuntimeException: 密码不能过于简单at com.ITGodRoad.exception.ExceptionDemo.updatePassword(ExceptionDemo.java:30)at com.ITGodRoad.exception.ExceptionDemo.main(ExceptionDemo.java:18)

可以看出,自定义异常,会将异常的处理权交给自己,而不是 JVM ,这样就避免了 JVM 遇到一些级别低的错误而使整个程序关闭。

在这里插入图片描述
在这里插入图片描述

 


7. 高级的自定义异常

可以自定义属性,例如添加异常级别(警告 warn 、错误 error 等),异常类型(业务异常、操作异常等),等其他自定义信息,还可以指定异常记录的输出位置,这样以后查看 log 就可以很轻松的定位程序问题所在了。

  • NormalException
package com.ITGodRoad.exception;import java.util.Map;import com.ITGodRoad.constant.Constant;public class NormalException extends RuntimeException {/****/private static final long serialVersionUID = 1L;private String level;private String errorType;private Map<String, String> data;private boolean isMessage;public Map<String, String> getData() {return data;}public void setData(Map<String, String> data) {this.data = data;}public String getLevel() {return level;}public String getErrorType() {return errorType;}public void setLevelError() {this.level = Constant.LEVEL_ERROR;}public void setErrorTypeBusiness() {this.errorType = Constant.ERROR_TYPE_BUSINESS;}public boolean isMessage() {return isMessage;}public NormalException(String errorMessageCode) {super(errorMessageCode);this.level = Constant.LEVEL_WARN;this.errorType = Constant.ERROR_TYPE_COMMUNICATION;this.data = null;this.isMessage = false;}// 判断是否是直接输出信息,false 则去数据库查询public NormalException(String errorMessageCode, boolean isMessage) {super(errorMessageCode);this.level = Constant.LEVEL_WARN;this.errorType = Constant.ERROR_TYPE_COMMUNICATION;this.data = null;this.isMessage = isMessage;}
}
  • MessageMasterService

@Service
@Transactional
public class MessageMasterService extends BaseService {@Autowiredprivate MessageMasterDao messageMasterDao;public String getMessage(String codeId) {log.info("codeId:" + codeId);if (Util.isEmptyString(codeId)) {return MessageCodes.DEFAULT_ERROR_DETAIL;}try {MessageMaster messageMaster = messageMasterDao.getMessageMasterById(Constant.IT_GOD_ROAD_WEB_SITE, codeId);if (Util.isNull(messageMaster)) {messageMaster = messageMasterDao.getMessageMasterById(Constant.IT_GOD_ROAD_WEB_SITE, MessageCodes.DEFAULT_ERROR);}if (Util.isNull(messageMaster)) {return "";}return messageMaster.getMessageDesc();} catch (Exception e) {return MessageCodes.DEFAULT_ERROR_DETAIL;}}
}
  • MessageMasterDao
@Repository
public class MessageMasterDao extends BaseDao {public MessageMaster getMessageMasterById(String type, String id) {log.info("type:" + type);log.info("id:" + id);MessageMasterId messageMasterId = new MessageMasterId();messageMasterId.setMessageType(type);messageMasterId.setMessageId(id);Session session = sessionFactory.getCurrentSession();MessageMaster messageMaster = session.get(MessageMaster.class, messageMasterId);return messageMaster;}}
  • MessageMaster

/*** MessageMaster generated by hbm2java*/
@Entity
@Table(name = "MESSAGE_MASTER")
public class MessageMaster implements java.io.Serializable {/*** */private static final long serialVersionUID = 1L;private MessageMasterId id;private String messageDesc;public MessageMaster() {}public MessageMaster(MessageMasterId id, String messageDesc) {this.id = id;this.messageDesc = messageDesc;}@EmbeddedId@AttributeOverrides({@AttributeOverride(name = "messageType", column = @Column(name = "MESSAGE_TYPE", nullable = false, length = 32)),@AttributeOverride(name = "messageId", column = @Column(name = "MESSAGE_ID", nullable = false, length = 32)) })public MessageMasterId getId() {return this.id;}public void setId(MessageMasterId id) {this.id = id;}@Column(name = "MESSAGE_DESC", nullable = false, length = 1024)public String getMessageDesc() {return this.messageDesc;}public void setMessageDesc(String messageDesc) {this.messageDesc = messageDesc;}}

 


【每日一面】

try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?在finally中return好吗?

注意!!! 在 finally 中改变返回值的做法是不好的,因为如果存在 finally 代码块,try中的 return 语句不会立马返回调用者,而是记录下返回值待 finally 代码块执行完毕之后再向调用者返回其值,然后如果在 finally 中修改了返回值,就会返回修改后的值。显然,在 finally 中返回或者修改返回值会对程序造成很大的困扰,C#中直接用编译错误的方式来阻止程序员干这种龌龊的事情,Java 中也可以通过提升编译器的语法检查级别来产生警告或错误。
catch 中 return 了 finally 还是会执行,在 return 前执行

在这里插入图片描述

这篇关于【年薪百万之IT界大神成长之路】JAVA 中的异常处理,阅后即焚!!!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/813454

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2