【面试干货】throw 和 throws 的区别

【面试干货】throw 和 throws 的区别

|-----------------------------|
| 💖The Begin💖点点关注,收藏不迷路💖 |

在Java中,throw和throws都与异常处理紧密相关,但它们在使用和含义上有明显的区别。

1、throw

throw 语句用于在方法体内明确地抛出一个异常。 当throw语句被执行时,它会立即终止当前方法的执行,并将指定的异常对象传递给调用该方法的代码。

重要概念:

  • throw 是具体向外抛出异常的动作:它抛出的是一个异常实例。

  • 执行 throw 一定是抛出了某种异常:在throw语句后,代码的执行会立即中断,并跳转到相应的异常处理代码(如catch块)。

1.1 示例

java 复制代码
package com.example;

public class ExceptionExample {

    public static void main(String[] args) {
        // 创建一个实例并调用可能抛出异常的方法
        // 注意:传递true来触发IllegalArgumentException异常
        ExceptionExample example = new ExceptionExample();
        example.exampleMethod(true); // 传递true以触发异常
        // 也可以尝试 example.exampleMethod(false); 来避免异常
    }

    public void exampleMethod(boolean someCondition) {
        try {
            // 假设这里有一些可能引发异常的代码
            if (someCondition) {
                // 如果someCondition为true,则抛出IllegalArgumentException异常
                // 提示:当someCondition为true时,将抛出异常
                throw new IllegalArgumentException("无效的参数");
            }
            // 如果someCondition为false,则不会抛出异常,并且可以继续执行下面的代码(如果有的话)
            // 提示:当someCondition为false时,不会抛出异常
        } catch (IllegalArgumentException e) {
            // 捕获IllegalArgumentException异常并打印堆栈跟踪
            // 提示:捕获到IllegalArgumentException异常,打印堆栈跟踪
            e.printStackTrace();
        }
        // 注意:catch块之后的代码将在捕获异常后继续执行,除非在catch块中再次抛出异常或遇到return语句
        // 提示:无论是否捕获到异常,此处的代码都会执行
        System.out.println("在可能的异常之后,方法继续执行。");
    }
}

由于main方法中调用exampleMethod时传递了true,因此会触发IllegalArgumentException,会在控制台看到异常的堆栈跟踪信息,并且随后会输出"在可能的异常之后,方法继续执行。"。

如果将main方法中的exampleMethod(true)改为exampleMethod(false),则不会抛出异常,并且只会输出"在可能的异常之后,方法继续执行。"。

2、throws

throws 关键字用于在方法声明中声明该方法可能会抛出的异常类型。

这并不意味着该方法一定会抛出这些异常,但它告诉方法的调用者需要准备处理这些类型的异常。

重要概念:

  • throws 主要是声明这个方法会抛出某种类型的异常:它允许方法的调用者知道需要捕获哪些类型的异常。

  • throws 表示出现异常的一种可能性:它并不保证方法在执行过程中一定会抛出这些异常。

2.1 示例

示例展示了如何在Java中定义一个可能抛出IOException的方法,并在该方法中模拟执行可能引发IOException的代码。当这个方法被调用时,如果发生IOException,调用者需要处理这个异常,或者继续向上抛出。

java 复制代码
package com.example;
import java.io.IOException;

public class ExceptionHandlingExample {

    // 定义一个可能抛出IOException的方法
    public void anotherExampleMethod() throws IOException {
        try {
            // 假设这里我们试图打开一个文件,但文件不存在,或者我们没有读取文件的权限
            // 这将会抛出IOException
            // new FileInputStream("nonexistentfile.txt");

            // 为了演示,我们直接抛出一个IOException
            throw new IOException("模拟的IO异常");
        } catch (IOException e) {
            // 在这个方法内部,我们选择处理这个异常
            // 但由于我们声明了throws IOException,所以我们选择不处理它,而是将它抛出
            throw e; // 或者使用 throw new IOException("新的错误信息", e); 来包装并重新抛出
        } finally {
            // finally块中的代码无论是否发生异常都会执行
            // 这是一个清理资源的好地方,比如关闭文件流或数据库连接
            System.out.println("finally块中的代码被执行了,用于清理资源。");
        }

        // 注意:由于我们在catch块中重新抛出了异常,所以这里的代码不会被执行
        // 因此,这行代码将会导致"无法访问的语句"编译错误
        // System.out.println("如果没有异常,这行代码将被执行。"); // 这行代码应该被删除或移到try块内部
    }

    public static void main(String[] args) {
        ExceptionHandlingExample example = new ExceptionHandlingExample();

        try {
            // 调用可能抛出IOException的方法
            example.anotherExampleMethod();
        } catch (IOException e) {
            // 在main方法中处理异常
            e.printStackTrace();
            System.out.println("捕获到了IOException,并进行了处理。");
        }

        // 注意:即使anotherExampleMethod抛出了异常,main方法中的后续代码仍然可以执行
        System.out.println("main方法继续执行...");
    }
}

anotherExampleMethod方法中抛出了一个IOException,并且这个异常被main方法中的catch块捕获并处理了。

当Java代码抛出一个异常且这个异常没有被立即捕获时,JVM(Java虚拟机)会开始寻找一个能够处理这个异常的catch块。

它首先会在抛出异常的try块中查找,如果没有找到,就会沿着方法调用栈向上查找,直到找到一个能够处理这个异常的catch块,或者直到到达方法调用栈的顶部(即程序的最顶层),这时JVM会终止程序并打印出未捕获的异常信息。

3、总结

1、throw 是实际抛出异常的动作,它中断方法的执行并传递异常对象。

2、throws 是声明方法可能会抛出的异常类型,它告诉方法的调用者需要准备处理这些异常。

|---------------------------|
| 💖The End💖点点关注,收藏不迷路💖 |

相关推荐
王嘉俊9255 分钟前
设计模式--享元模式:优化内存使用的轻量级设计
java·设计模式·享元模式
2301_803554521 小时前
C++联合体(Union)详解:与结构体的区别、联系与深度解析
java·c++·算法
EnCi Zheng1 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端
烙印6011 小时前
Spring容器的心脏:深度解析refresh()方法(上)
java·后端·spring
为什么我不是源代码1 小时前
JPA读取数据库离谱问题-No property ‘selectClassByName‘ found-Not a managed type
java·sql
Lisonseekpan1 小时前
Guava Cache 高性能本地缓存库详解与使用案例
java·spring boot·后端·缓存·guava
我真的是大笨蛋2 小时前
Redis的String详解
java·数据库·spring boot·redis·spring·缓存
心态特好2 小时前
Jwt非对称加密的应用场景
java
DoraBigHead2 小时前
🧭 React 理念:让时间屈服于 UI —— 从同步到可中断的演化之路
前端·javascript·面试
敢敢J的憨憨L2 小时前
GPTL(General Purpose Timing Library)使用教程
java·服务器·前端·c++·轻量级计时工具库