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


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

1、throw

throw 语句用于在方法体内明确地抛出一个异常。

重要概念:

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

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

1.1 示例

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("在可能的异常之后,方法继续执行。");
    }
}

【面试干货】throw 和 throws 的区别-LMLPHP
由于main方法中调用exampleMethod时传递了true,因此会触发IllegalArgumentException,会在控制台看到异常的堆栈跟踪信息,并且随后会输出“在可能的异常之后,方法继续执行。”。

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

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

2、throws

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

重要概念:

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

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

2.1 示例

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

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方法继续执行...");
    }
}

【面试干货】throw 和 throws 的区别-LMLPHP
anotherExampleMethod方法中抛出了一个IOException,并且这个异常被main方法中的catch块捕获并处理了。

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

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

3、总结

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

2、throws 是声明方法可能会抛出的异常类型,它告诉方法的调用者需要准备处理这些异常。
【面试干货】throw 和 throws 的区别-LMLPHP


06-21 07:17