首页 > 编程语言 >Java 异常相关(二):异常处理机制的补充,自定义异常的使用等

Java 异常相关(二):异常处理机制的补充,自定义异常的使用等

时间:2024-05-23 22:55:22浏览次数:32  
标签:Java 自定义 抛出 try finally catch 异常

一、前言

记录时间 [2024-05-22]

前置文章:
Java 异常相关:异常体系结构,异常与错误的区别等

本文讲述 Java 异常相关知识,对异常处理机制进行补充,以及自定义异常的方式。


文章对异常知识的描述显然是笼统而简洁的,对于异常的学习,更应注重平时的积累和整理。


二、异常处理机制

Java 通过 try-catch-finally 语句块来捕获和处理异常。5 个处理机制关键字如下:

  • try - 用于包围可能会抛出异常的代码块。
  • catch - 紧跟在 try 块之后,用于捕获并处理特定类型的异常。
  • finally - 无论是否发生异常,都会执行的代码块,通常用于释放资源等善后工作
  • throw - 用于在代码中手动抛出一个异常实例。
  • throws - 用于声明方法可能抛出的异常类型,将异常处理的责任转移给方法的调用者。

1. try-catch-finally

语法

// try 和 catch 是必须的,finally 可以不要
// 可以在 finally 中关闭一些 IO、资源

try {
	// try 监控区域
} catch (ArithmeticException e) { 
    // catch 捕获异常
} finally { 
    // 处理善后工作
}

简单示例

以下是一个使用 try-catch-finally 语句处理异常的简单示例。

public static void main(String[] args) {
    int a = 1;
    int b = 0;

    // try 和 catch 是必须的,finally 可以不要
    // 可以在 finally 中关闭一些 IO、资源

    try { // try 监控区域
        System.out.println(a/b);
    } catch (ArithmeticException e) { // catch 捕获异常
        System.out.println("程序出现异常,变量 b 不能为 0");
    } finally { // 处理善后工作
        System.out.println("finally");
    }

}

使用 try-catch-finally 语句捕获一个被除数为 0 的异常:

  • 把需要监控的代码放在 try 区域;
  • 经由 catch 捕获异常后,我们可以做一些处理,比如输出问题;
  • 其中,catch 中的参数是想要捕获的异常类型,如 ArithmeticException
  • 最后,在 finally 中完成善后工作,无论异常是否被捕获,finally 最终都会执行。

错误 Error 也可以被捕获。

如果想要捕获多种异常,可以写多个 catch 语句块。

例如:

// 快捷键 Ctrl + Alt + T,快速生成代码块

try { // try 监控区域
    System.out.println(a/b);
} catch (ArithmeticException e) { // catch 捕获异常
    System.out.println("程序出现异常,变量 b 不能为 0");
} catch (Exception e) {
    System.out.println("Exception");
} catch (Throwable t) {
    System.out.println("Throwable");
} finally { // 处理善后工作
    System.out.println("finally");
}

需要注意的是,catch 语句块自上而下层层递进,范围大的异常或错误捕获需要写在下面


2. throw

在 Java 中,throw 关键字用于手动抛出一个异常。当需要在代码中表示某种异常情况发生时,就可以使用 throw 来创建并抛出一个异常对象。

这通常用于自定义异常处理逻辑,或者在方法内部检测到不符合条件的情况时主动抛出异常。

通过这种方式,可以根据程序的逻辑主动控制异常的抛出,使得异常处理更加灵活和精确。

语法

throw new ExceptionType("异常信息");

其中,ExceptionType 是用户希望抛出的异常类型,可以是具体的异常类名,如 IllegalArgumentExceptionNullPointerException 等,也可以是自定义的异常类。

紧跟在后面的字符串是可选的,用于提供异常的具体描述信息。

简单示例

假设我们有一个方法,该方法接收一个年龄参数,如果年龄小于 0,我们希望抛出一个 IllegalArgumentException 来表示非法参数。

public class ThrowExample {
    public static void main(String[] args) {
        try {
            checkAge(-1); // 这将抛出异常
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage()); // 打印异常信息
        }
    }

    // 检查年龄的方法
    public static void checkAge(int age) throws IllegalArgumentException {
        if (age < 0) {
            throw new IllegalArgumentException("年龄不能为负数");
        } else {
            System.out.println("年龄合法");
        }
    }
}

在这个例子中,checkAge 方法检查传入的年龄是否为负数。如果是,就通过 throw new IllegalArgumentException("年龄不能为负数") 抛出一个带有详细信息的 IllegalArgumentException

main 方法中,我们通过 try-catch 块捕获这个异常,并打印出异常信息。


3. throws

在 Java 中,throws 关键字用于声明方法可能抛出的异常类型,它告诉调用者这个方法执行时可能会遇到的问题,从而提醒调用者做出相应的异常处理。

使用 throws 关键字可以将异常处理的责任上交给方法的调用者。

通过 throws 声明异常,可以使代码更加清晰地表明哪些异常需要调用者关注并处理,有助于提高程序的可读性和健壮性。

语法

在方法签名后使用 throws 关键字,后面跟着可能抛出的一个或多个异常类型,用逗号分隔。

public returnType methodName() throws ExceptionType1, ExceptionType2 {
    // 方法体
}

简单示例

考虑一个读取文件并返回其内容的函数,这个操作可能会抛出 IOException

我们可以使用 throws 来声明这个方法可能抛出的异常:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ThrowsExample {

    public static void main(String[] args) {
        try {
            String content = readFileContent("example.txt");
            System.out.println(content);
        } catch (IOException e) {
            System.out.println("读取文件时发生错误:" + e.getMessage());
        }
    }

    // 声明可能抛出 IOException 的方法
    public static String readFileContent(String filePath) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(filePath));
        StringBuilder content = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            content.append(line).append("\n");
        }
        reader.close();
        return content.toString();
    }
}

在这个例子中,readFileContent 方法可能抛出 IOException,因为它涉及到文件读取操作。

因此,我们在方法签名中使用 throws IOException 来声明这一可能性。

main 方法中调用 readFileContent 时,我们通过 try-catch 块来捕获并处理这个可能发生的异常。


三、自定义异常

使用 Java 内置的异常类可以描述在编程时出现的大部分异常情况。但是,在 Java 中,可能需要根据特定的业务逻辑或应用需求定义自己的异常类,这就是自定义异常。

自定义异常通常继承自 Exception 类或其子类(对于运行时异常,则继承自 RuntimeException)。

自定义异常增强了程序的清晰度和可维护性,使得异常处理更贴近应用程序的具体逻辑。

下面是如何创建和使用自定义异常的简单步骤和示例。


1. 步骤

在程序中使用自定义异常类,大体可分为以下几个步骤:

  • 定义异常类 - 新建一个类,继承自 Exception 或其子类(如 IOExceptionRuntimeException 等),根据异常的性质选择合适的基类。
  • 构造方法 - 至少定义一个构造方法,通常接受一个字符串参数(异常消息),并调用超类的构造方法传递这个消息。
  • 捕获并处理异常
    • 在需要抛出自定义异常的地方,使用 throw new YourException("异常信息") 来抛出异常;
    • 如果在当前抛出异常的方法中处理异常,可以使用 try-catch 语句捕获并处理;
    • 否则在方法的声明处通过 throws 关键字指明要抛出给方法调用者的异常。

2. 示例

假设我们要为一个学生管理系统定义一个特定的异常,当尝试注册一个已经存在的学生 ID 时抛出。

我们可以创建一个 StudentAlreadyExistsException,让这个类继承 Exception 为父类,它就变成了一个自定义异常类,处理特定的异常。

// 自定义异常类
public class StudentAlreadyExistsException extends Exception {
    
    public StudentAlreadyExistsException(String message) {
        // 调用Exception的构造方法传递异常信息
        super(message); 
    }
    
}

然后,我们在其他方法中,使用这个自定义异常类处理一些特定的异常。

// 使用自定义异常的类
public class StudentManager {
    private List<Student> students = new ArrayList<>();

    public void registerStudent(Student student) throws StudentAlreadyExistsException {
        for (Student s : students) {
            if (s.getId().equals(student.getId())) {
                // 主动抛出异常给上述自定义异常类
                throw new StudentAlreadyExistsException("学生 ID 已存在,无法注册。");
            }
        }
        students.add(student);
        System.out.println("学生注册成功。");
    }

    public static void main(String[] args) {
        StudentManager manager = new StudentManager();
        Student student = new Student("S001", "张三");

        try {
            manager.registerStudent(student);
            manager.registerStudent(student); // 尝试再次注册相同的 ID
        } catch (StudentAlreadyExistsException e) {
            System.out.println(e.getMessage());
        }
    }
}

在这个示例中:

  • 我们首先定义了一个 StudentAlreadyExistsException 类,它继承自 Exception
  • 然后,在 StudentManager 类的 registerStudent 方法中,当我们检测到尝试注册的学生 ID 已存在时,就抛出这个自定义异常。
  • main 方法中,我们通过 try-catch 块捕获并处理这个异常。

四、总结

本文讲述 Java 异常相关知识,对异常处理机制进行补充,以及自定义异常的方式。

  • 处理运行时异常时,在逻辑上合理规避,同时使用 try-catch 辅助处理;
  • 在多重 catch 块后面,可以加一个 catch (Exception e) 来处理可能会被遗漏的异常;
  • 对于不确定的代码,也可以加上 try-catch,处理潜在的异常;
  • 尽量去处理异常,切忌只是简单地调用 printStackTrace() 去打印输出;
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定;
  • 尽量添加 finally 语句块去释放占用的资源。

一些参考资料

狂神说 Java 零基础:https://www.bilibili.com/video/BV12J41137hu/
TIOBE 编程语言走势: https://www.tiobe.com/tiobe-index/
Typora 官网:https://www.typoraio.cn/
Oracle 官网:https://www.oracle.com/
Notepad++ 下载地址:https://notepad-plus.en.softonic.com/
IDEA 官网:https://www.jetbrains.com.cn/idea/
Java 开发手册:https://developer.aliyun.com/ebook/394
Java 8 帮助文档:https://docs.oracle.com/javase/8/docs/api/

标签:Java,自定义,抛出,try,finally,catch,异常
From: https://blog.csdn.net/Sareur_1879/article/details/139128088

相关文章

  • Java enum 枚举类
    JavaEnum枚举类概述枚举类型本质上也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。如果针对于某个类,其实例是确定个数,则推荐将此类声明为枚举类。如果枚举类的实例只有一个,则可以看作时单例的实现方式。枚举类的实现JDK5.0之前classS......
  • Java中负载均衡
    文章目录负载均衡背景如何实现负载均衡呢常见的负载均衡有三种负载均衡的作用范围负载均衡的的常用算法负载均衡背景在互联网的发展早期由于用户量较少业务需求比较简单对于软件应用来说我们只需要一台高配的服务器既可以完成整个业务的支撑这样的软件架构成为......
  • 自定义Feign配置
    java代码的方式写一个配置类publicclassFeignConfig{/***将契约改为feign原生的默认契约。这样就可以使用feign自带的注解了。*@return默认的原生契约*/@BeanpublicContractfeignContract(){returnnewContract.Default......
  • Java中继承与接口的区别(浅谈)
    在Java中,继承和接口是两种不同的方式来实现代码的复用和扩展。以下是它们之间的主要区别:1.继承:继承是面向对象编程中的一种方式,允许一个类继承另一个类的属性和方法。继承的主要目的是为了实现代码的复用,即子类可以继承父类的属性和方法,从而避免重复编写相同的代码。此外,继......
  • Java练习(并发模式)
    设计一个简单的生产者-消费者模型,其中生产者负责生成数据,消费者负责处理数据。为了在生产者和消费者之间传递数据,使用一个有界缓冲区(例如,`ArrayBlockingQueue`)作为它们之间的通信通道。要求:1.创建一个`Producer`类,该类包含一个`produce()`方法,用于生成数据。生成的数据应该......
  • Java 形参 实参 参数传递
    Java形参实参在Java中,形参和实参是两个重要的概念,它们分别指形式参数和实际参数。形参:形式参数是在方法定义时用于接收调用该方法时传递的参数。它只在方法内部有效,方法结束后就消失了。实参:实际参数是在调用方法时传递给方法的参数,它可以是常量、变量、表达式、或者方法的......
  • 框架(Java相关)基础
    框架前置知识时间:2024-05-20星期一学习内容Maven构建工具Maven的核心特性Maven的依赖管理Maven的工程打包工厂模式设计模式工厂模式工厂模式的引用场景反射机制反射及作用反射的四个核心类反射在项目中的应用Lambda表达式Lamb......
  • 计算机Java项目|基于springboot的网上购物商城系统研发
    作者主页:编程指南针作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互......
  • 计算机Java项目|基于Springboot甘肃非物质文化网站的设计与开发
    作者主页:编程指南针作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互......
  • 计算机Java项目|Springboot教师工作量管理系统
    作者主页:编程指南针作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互......