尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Java基础:异常(三)

Java基础:异常(三) Java基础异常三阅读本文你将获得彻底搞懂finally中有return时到底返回哪个值清晰辨析throws和throw的核心区别与使用场景。掌握 JDK7 更优雅的try-with-resources资源管理语法。学会如何规范地编写和使用自定义业务异常。适合人群Java初学者 / 校招备考生 / 需要系统梳理异常机制的开发者⏱️预计阅读时间15分钟 | 建议收藏后配合IDE边看边敲文章目录Java基础异常三1. Java异常体系1.1 程序错误的分类1.2 异常的分类1. 检查型异常Checked Exception2. 非检查型异常Unchecked Exception2. 异常的捕获与处理2.1 try-catch 机制2.2 finally 块与执行顺序2.3 try-with-resources (现代Java推荐写法)3. 异常的抛出throw 与 throws4. 自定义异常与异常链4.1 定义业务异常4.2 业务场景实战5. 异常使用的最佳实践避坑指南 课后思考与互动 Java基础系列导航1. Java异常体系Java的异常体系是用于处理运行时错误和其他异常情况的重要机制。它基于一个层次结构其中Throwable是所有错误和异常的基类。在Java中主要有两种类型的可抛出对象Error和Exception。合理的异常处理机制是保证程序健壮性的基石。1.1 程序错误的分类在编写程序时我们通常会遇到以下三类错误编译错误Compilation Error在源代码被编译器处理时发生。通常是因为违反了Java语法规则如拼写错误、缺少分号、类型不匹配编译器会直接报错程序无法生成.class文件。运行错误Runtime Error程序在运行期间发生的错误。在Java中这通常表现为异常Exception或错误Error。例如除以零、数组越界、内存溢出等。逻辑错误Logical Error程序能正常编译和运行但结果不符合预期。例如计算公式写错、循环条件设置不当。这类错误不会抛出异常只能通过代码审查和单元测试来排查。1.2 异常的分类Java中的异常Exception主要分为两大类1. 检查型异常Checked Exception在编译时会被编译器强制检查。如果方法可能抛出此类异常必须使用try-catch捕获或者在方法签名上使用throws声明否则编译无法通过。通常表示程序外部环境引起的可恢复问题。常见检查型异常说明IOException输入输出流异常如读写文件失败SQLException数据库SQL操作异常FileNotFoundException尝试访问不存在的文件ClassNotFoundException动态加载类时找不到对应的.class文件InterruptedException线程在等待、休眠或被占用时被中断2. 非检查型异常Unchecked Exception指RuntimeException运行时异常及其子类以及Error。在编译时不会被强制检查通常是由程序逻辑错误引起的开发者应通过严谨的代码逻辑来避免。常见运行时异常说明NullPointerException空指针异常访问了未初始化的对象引用ArrayIndexOutOfBoundsException数组下标越界异常ArithmeticException算术异常如整数除以零NumberFormatException字符串转换为数字时格式不正确ClassCastException对象强制类型转换失败2. 异常的捕获与处理2.1 try-catch 机制在try块中放置可能产生异常的代码后续紧跟一个或多个catch块来捕获并处理特定类型的异常。一旦try块中发生异常代码会立即跳转到匹配的catch块try块中异常发生点之后的代码将不再执行。基础语法try{// 可能会抛出异常的代码}catch(ExceptionType1e){// 处理 ExceptionType1 类型的异常}catch(ExceptionType2e){// 处理 ExceptionType2 类型的异常}JDK 7 多重异常捕获从 JDK 7 开始如果多个catch块的处理逻辑完全相同可以使用|将异常类型合并使代码更简洁importjava.util.Scanner;publicclassMultiCatchTest{publicstaticvoidmain(String[]args){ScannerscannernewScanner(System.in);System.out.println(请输入两个数);intxscanner.nextInt();intyscanner.nextInt();int[]mnewint[10];try{intzx/y;// 可能抛出 ArithmeticExceptionSystem.out.println(除法结果z);m[10]10;// 可能抛出 ArrayIndexOutOfBoundsException}catch(ArithmeticException|ArrayIndexOutOfBoundsExceptione){System.out.println(捕获到异常e.toString());}}}运行结果请输入两个数 10 0 捕获到异常java.lang.ArithmeticException: / by zero 请输入两个数 10 2 除法结果5 捕获到异常java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10异常信息获取方式e.getMessage()获取异常的简短描述信息。e.toString()获取异常类名和描述信息。e.printStackTrace()打印完整的异常堆栈轨迹排查问题时最常用。2.2 finally 块与执行顺序finally块通常用于释放资源如关闭数据库连接、IO流等。它的核心特性是无论是否发生异常无论 try/catch 中是否有 return 语句finally 块中的代码几乎总会被执行。执行顺序剖析如果try或catch中有return语句finally会在return之前执行。publicclassFinallyTest{publicstaticvoidmain(String[]args){System.out.println(方法返回值testReturn());}publicstaticinttestReturn(){try{intx10/0;// 触发异常return1;}catch(ArithmeticExceptione){System.out.println(进入 catch 块);return2;// 准备返回 2}finally{System.out.println(进入 finally 块);// 注意如果在 finally 中写 return会覆盖 try/catch 中的 return 值// 实际开发中极度不推荐在 finally 中写 return。}}}运行结果进入 catch 块 进入 finally 块 方法返回值2⚠️唯一不执行 finally 的特例如果在try或catch中调用了System.exit(0)强行退出 JVM或者 JVM 崩溃/断电finally将不会执行。2.3 try-with-resources (现代Java推荐写法)从 JDK 7 开始Java 引入了try-with-resources语法用于自动关闭实现了AutoCloseable接口的资源彻底告别繁琐的 finally 关闭流代码。importjava.io.FileReader;importjava.io.BufferedReader;publicclassResourceTest{publicstaticvoidmain(String[]args){// 在 try() 括号内声明资源代码块执行完毕后会自动调用 close() 方法try(BufferedReaderbrnewBufferedReader(newFileReader(test.txt))){System.out.println(br.readLine());}catch(Exceptione){e.printStackTrace();}// 无需再写 finally 去手动 br.close()}}3. 异常的抛出throw 与 throws在Java中抛出异常有两个关键字它们长相相似但作用截然不同特性throwthrows位置方法体内部方法签名上作用抛出一个具体的异常实例声明方法可能抛出的异常类型数量一次只能抛出一个异常对象可声明多个异常类型逗号分隔处理责任由当前方法捕获或向上抛给调用者明确告知调用者你必须处理这些异常代码实战importjava.io.FileNotFoundException;publicclassThrowTest{publicstaticvoidmain(String[]args){// 调用者必须处理 checkPersonInfo 声明的检查型异常try{checkPersonInfo(张,10);}catch(FileNotFoundExceptione){System.out.println(main方法捕获异常e.getMessage());}}// throws声明该方法可能抛出 FileNotFoundExceptionpublicstaticvoidcheckPersonInfo(Stringname,intage)throwsFileNotFoundException{if(age18){// throw抛出运行时异常不需要在方法签名上声明thrownewIllegalArgumentException(年龄必须在18岁以上当前age);}if(name.length()2){// throw抛出检查型异常必须配合 try-catch 或 throws 使用thrownewFileNotFoundException(姓名长度不合法name);}System.out.println(校验通过);}}运行结果main方法捕获异常姓名长度不合法张(注如果传入年龄为10则会先抛出IllegalArgumentException导致程序中断因为它是运行时异常且未被捕获。)4. 自定义异常与异常链在实际企业开发中JDK内置的异常往往无法精确表达业务错误如“用户余额不足”、“库存超卖”。这时我们需要自定义异常。4.1 定义业务异常通常继承RuntimeException免检异常推荐或Exception受检异常。// 自定义运行时异常publicclassAgeExceptionextendsRuntimeException{publicAgeException(Stringmessage){super(message);}// 支持异常链保留原始异常信息publicAgeException(Stringmessage,Throwablecause){super(message,cause);}}4.2 业务场景实战publicclassUserService{publicvoidregisterUser(Stringname,intage){if(age0||age150){// 抛出自定义异常thrownewAgeException(用户注册失败年龄 age 不合法);}System.out.println(用户 name 注册成功);}publicstaticvoidmain(String[]args){UserServiceservicenewUserService();try{service.registerUser(张三,200);}catch(AgeExceptione){// 捕获并处理自定义异常System.err.println(业务拦截e.getMessage());}}}关于异常链Exception Chaining在捕获底层异常如SQLException并抛出自定义业务异常时务必将原始异常作为 cause 传入如throw new BizException(数据库错误, e)。否则会导致底层堆栈信息丢失给后期排查带来灾难。5. 异常使用的最佳实践避坑指南不要使用异常来控制业务流程异常对象的创建需要抓取当前线程的完整栈帧性能开销极大。正常的业务逻辑判断如if (obj null)远比try-catch(NullPointerException)高效。尽早抛出延迟捕获在发现错误的地方立即throw在能够真正处理该错误如给用户返回友好提示、记录日志、回滚事务的层级再去catch。不要为了消除编译警告而写空的catch块释放资源首选try-with-resources避免在finally中手动写close()不仅代码冗长且close()本身也可能抛出异常容易掩盖原始异常。日志记录要完整使用日志框架如 SLF4J/Logback记录异常时一定要传入异常对象本身log.error(操作失败, e);而不是仅仅log.error(e.getMessage());。 课后思考与互动思考题以下代码的最终返回值是多少为什么publicstaticinttestFinally(){inti1;try{returni;}finally{i2;}}欢迎在评论区留下你的答案和解析我会挑选优质评论进行置顶 Java基础系列导航上一篇Java基础面向对象二本篇Java基础异常三下一篇Java基础常用类四如果这篇文章对你有帮助请不要吝啬你的点赞、收藏⭐和关注➕这是我持续输出高质量技术文章的最大动力我们下一篇见
返回列表