【Java基础巩固系列】异常

业务背景

业务开发中,总会遇到代码出现异常的情况,不合理的异常处理或不处理异常除了影响业务功能和中断业务功能外,还会增加排查问题的难度。所以我们要学会正确的使用异常处理。合理的异常处理能减少很多潜在的问题,是提高代码鲁棒性的重要手段。

什么是异常

异常是程序在运行过程中发生的意外情况,通常是由外部因素或程序逻辑中的特殊情况引起的。例如文件不存在,网络连接中断,用户输入不合法等。和bug有所不一样,bug是指程序中存在的缺陷或错误,通常是由开发者的逻辑错误,疏忽或需求理解不准确导致的。它们都有可能导致程序出错。

异常的分类

在Java语言中,针对异常提供了异常处理机制,Java把异常分为两类,分别是受检异常和非受检异常。

  • 受检异常:程序在编译期间出现的异常,如文件不存在、网络连接失败等。
  • 非受检异常:又叫做运行时异常(RunTimeException),通常是程序在运行期间逻辑导致的,如空指针异常、数组越界等。
特性 运行时异常(非受检异常) 受检异常(Checked Exception)
发生阶段 运行期间 编译期间
是否强制处理
典型例子 NullPointerExceptionArrayIndexOutOfBoundsException IOExceptionSQLException
原因 程序逻辑错误或外部条件 外部因素(如文件不存在、网络中断)

异常的处理

针对这两种异常,java提供了异常处理机制,即使用throws、throw(用于手动抛出异常)和使用try-catch-finally。

  • thorws:用于声明方法可能抛出的异常,向上抛出异常,即把异常丢给调用方处理。
  • try-catch- finally:用于捕获并处理异常,在catch内部完成异常处理。finally块中的代码都会执行,通常用于释放资源。

例如下面的代码,使用了两种处理机制,一个是try-catch在方法中闭环,一个时throws抛出异常。

java 复制代码
package com.example.demo;
​
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
​
/**
* @author lijianxiong
*/
public class NetWorkException {
   public static void main(String[] args) {
       exceptionDemoByTryCatch();
  }
​
   public static void exceptionDemoByTryCatch() {
       try {
           URL url = new URL("https://nonexistentwebsite.example");
           HttpURLConnection connection = (HttpURLConnection) url.openConnection();
           connection.connect();
      } catch (IOException e) {
           System.out.println("try-catch方法捕获异常,网络连接出现异常: " + e.getMessage());
      }
  }
​
   public static void exceptionDemoByThrows() throws IOException {
       URL url = new URL("https://nonexistentwebsite.example");
       HttpURLConnection connection = (HttpURLConnection) url.openConnection();
       connection.connect();
  }
​
}

自定义异常

在实际开发中,当Java提供的Java异常类不满足业务需求时,比如要根据业务内容处理更加细致的异常,如要判断用户年龄,判断名字是否合法等。那么我们可以使用自定义异常。自定义异常通常会继承Exception类或者它的子类。

  • 继承Exception成为受检异常:如果自定义类直接继承Exception类,那么它就是一个受检异常,它使用时必须显示的处理。例如定义一个用户年龄不合法的异常。

    java 复制代码
    // 自定义受检异常
    public class InsufficientBalanceException extends Exception {
       public InsufficientBalanceException(String message) {
           super(message);
      }
    }
    ​
    // 业务类
    public class BankAccount {
       private double balance;
    ​
       public BankAccount(double balance) {
           this.balance = balance;
      }
    ​
       public void withdraw(double amount) throws InsufficientBalanceException {
           if (amount > balance) {
               throw new InsufficientBalanceException("余额不足,当前余额: " + balance);
          }
           balance -= amount;
           System.out.println("取款成功,剩余余额: " + balance);
      }
    }
    ​
    // 测试类
    public class Main {
       public static void main(String[] args) {
           BankAccount account = new BankAccount(1000);
           try {
               account.withdraw(1500); // 尝试取款
          } catch (InsufficientBalanceException e) {
               System.out.println("捕获到异常: " + e.getMessage());
          }
      }
    }
  • 继承RunTimeException类的自定义非受检异常: 在编译时不强制要求处理,以下是一个示例:

    typescript 复制代码
    // 自定义非受检异常
    class CustomUncheckedException extends RuntimeException {
       public CustomUncheckedException(String message) {
           super(message);
      }
    }
    ​
    public class UncheckedExceptionExample {
       public static void methodWithUncheckedException() {
           throw new CustomUncheckedException("这是一个自定义非受检异常");
      }
    ​
       public static void main(String[] args) {
           // 这里可以不捕获异常,编译能通过
           methodWithUncheckedException(); 
      }
    }

总结

  • 自定义异常通过继承Exception和RunTimeException实现。
  • 自定义异常可以更好的表示特定业务。
  • 异常处理可以提供清晰的错误信息和异常链,方便调试和维护。
相关推荐
神奇的程序员3 小时前
从已损坏的备份中拯救数据
运维·后端·前端工程化
oden4 小时前
AI服务商切换太麻烦?一个AI Gateway搞定监控、缓存和故障转移(成本降40%)
后端·openai·api
李慕婉学姐5 小时前
【开题答辩过程】以《基于Android的出租车运行监测系统设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·后端·vue
m0_740043735 小时前
SpringBoot05-配置文件-热加载/日志框架slf4j/接口文档工具Swagger/Knife4j
java·spring boot·后端·log4j
用户47949283569155 小时前
面试官问"try-catch影响性能吗",我用数据打脸
前端·javascript·面试
沐雪架构师5 小时前
大模型Agent面试精选15题(第四辑)-Agent与RAG(检索增强生成)结合的高频面试题
面试·职场和发展
未若君雅裁5 小时前
JVM面试篇总结
java·jvm·面试
YoungHong19926 小时前
面试经典150题[072]:从前序与中序遍历序列构造二叉树(LeetCode 105)
leetcode·面试·职场和发展
招风的黑耳6 小时前
我用SpringBoot撸了一个智慧水务监控平台
java·spring boot·后端
Miss_Chenzr6 小时前
Springboot优卖电商系统s7zmj(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端