Java 异常

一、什么是异常?

        想象一下,你在路上开车,突然发动机故障灯亮了。这时候你知道可能出了问题,需要检查一下。程序也是如此——在运行过程中,也会遇到各种"突发状况",我们称之为异常

比如我们经常遇到的:

//算术异常:除数为零
System.out.println(10 / 0);

//数组越界异常
int[] arr = {1, 2, 3};
System.out.println(arr[100]);

//空指针异常
String str = null;
System.out.println(str.length());

Java 为各种异常情况提供了对应的异常类,帮助我们精准地定位和处理问题。

二、异常的体系结构

Java 的异常体系结构清晰且层次分明:

Throwable
    ├── Error(不可处理,如内存溢出)
    └── Exception(可处理)
          ├── IOException(编译时异常)
          └── RuntimeException(运行时异常)

  • Error:指严重问题,如内存溢出(OutOfMemoryError),通常无法处理

  • Exception:程序员可以通过代码处理的异常,是我们关注的重点

三、异常的分类

3.1 编译时异常

在编译期间就能被发现的异常,必须处理否则无法通过编译。

//必须处理 CloneNotSupportedException
@Override
public Person clone() throws CloneNotSupportedException {
    return (Person)super.clone();
}

3.2 运行时异常

程序运行期间发生的异常,如空指针、数组越界等。

四、异常处理的两种哲学

4.1 LBYL(Look Before You Leap)

事前检查,防患于未然

if (file.exists()) {
    // 读取文件
} else {
    // 处理文件不存在的情况
}

4.2 EAFP(It's Easier to Ask Forgiveness than Permission)

先操作,遇到问题再处理

try {
    //读取文件
} catch (FileNotFoundException e) {
    //处理文件不存在的情况
}

Java 主要采用 EAFP 风格,通过五个关键字实现异常处理:throwtrycatchfinallythrows

五、异常的处理方式

5.1 抛出异常(throw)

public static int getElement(int[] array, int index) {
    if (array == null) {
        throw new NullPointerException("数组不能为null");
    }
    if (index < 0 || index >= array.length) {
        throw new ArrayIndexOutOfBoundsException("索引越界");
    }
    return array[index];
}

5.2 声明异常(throws)

public void readFile(String filename) throws FileNotFoundException {
    if (!filename.equals("config.ini")) {
        throw new FileNotFoundException("配置文件不存在");
    }
    //读取文件
}

5.3 捕获异常(try-catch)

try {
    //可能抛出异常的代码
    config.openConfig("config.txt");
} catch (FileNotFoundException e) {
    //处理异常
    System.out.println("文件未找到: " + e.getMessage());
    e.printStackTrace();
} finally {
    //无论是否发生异常都会执行
    System.out.println("资源清理操作");
}

六、异常处理流程

当异常发生时,JVM 会沿着方法调用栈向上寻找合适的异常处理器。如果一直找不到,最终会交给 JVM 处理,导致程序终止。

public static void main(String[] args) {
    try {
        func();
    } catch (Exception e) {
        e.printStackTrace(); //打印调用栈信息
    }
}

public static void func() {
    int[] arr = {1, 2, 3};
    System.out.println(arr[100]); //这里发生异常
}

七、自定义异常

Java 允许我们创建自己的异常类来表示特定的业务异常。

//自定义用户名异常
class UserNameException extends Exception {
    public UserNameException(String message) {
        super(message);
    }
}

//自定义密码异常
class PasswordException extends Exception {
    public PasswordException(String message) {
        super(message);
    }
}

//使用自定义异常
public void login(String username, String password) 
    throws UserNameException, PasswordException {
    
    if (!isValidUsername(username)) {
        throw new UserNameException("用户名错误");
    }
    if (!isValidPassword(password)) {
        throw new PasswordException("密码错误");
    }
    //登录成功
}

八、重要注意事项

  1. try-catch-finally 中,finally 块总是执行,常用于资源清理

  2. 捕获异常时,子类异常应该放在父类异常之前

  3. 不要过度使用异常处理,正常流程控制应该用条件语句

  4. 异常处理应该提供有意义的错误信息

  5. 日志记录是异常处理的重要组成部分

总结

        异常处理是 Java 编程中不可或缺的一部分。良好的异常处理可以使程序更加健壮和易于维护。记住:不要忽视异常,也不要过度使用异常。根据具体情况选择合适的处理方式,让程序在遇到问题时能够优雅地降级或恢复。希望本文能帮助你更好地理解和使用 Java 异常处理机制!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值