Java throw 和 throws 关键字
在 Java 异常处理中,throw关键字用于从方法或构造函数中显式抛出异常。throws关键字用于声明该方法或构造函数可能抛出的异常列表。
1.throw
在深入研究之前,让我们先了解一下有关throw关键字的基本知识。
1.1. 句法
要从方法或构造函数抛出异常,请使用throw 关键字和异常类的实例。
public void method() { //an unexpected event occured throw new CustomException("message"); }
1.2. 处理已检查与未检查的异常
如果我们从方法中抛出未经检查的异常,则不需要处理异常或在throws子句中声明。例如,NullPointerException
是一个未经检查的异常。
//处理未经检查的异常不是强制性的 public class JavaExample { public static void main(String[] args) { method(); } public static void method( ) { throw new NullPointerException(); } }
但是,如果我们使用throw语句抛出已检查的异常,则必须在catch 块中处理异常,或者方法必须使用 throws 声明显式声明它。例如,FileNotFoundException
是一个受检查的异常。
//必须处理已检查的异常 public class JavaExample { public static void main(String[] args) { try { method(); } catch (FileNotFoundException e) { e.printStackTrace(); } } public static void method() throws FileNotFoundException { throw new FileNotFoundException(); } }
Error
在 Java 中,和的每个子类RuntimeException
都是未经检查的异常。已检查异常是该类下的所有其他Throwable
内容。
1.3. 异常传播
异常从一个方法传播到另一个方法,沿着调用堆栈向上传播,直到被捕获。因此,如果 a() 调用 b(),b() 调用 c(),c() 调用 d(),并且如果 d() 抛出异常,则异常将从 d 传播到 c,再到 b 到 a,除非这些方法之一捕获例外。
异常处理程序的搜索从发生错误的方法开始,并以与调用方法相反的顺序继续遍历调用堆栈,如上所述。
当找到适当的处理程序(catch块)时,运行时系统将异常传递给处理程序。如果未找到异常处理程序,则异常将到达 JVM 的默认异常处理程序,该处理程序将异常详细信息打印到日志并终止应用程序。
2. Throws
Java throws关键字用于声明方法执行过程中可能发生的异常列表。
2.1. 句法
要声明异常列表,请使用throws关键字和异常类名称。
public static void method( ) throws FileNotFoundException, ConnectionException { //code }
2.2. 允许抛出已检查和未检查的异常
我们可以使用 throws 子句声明两种类型的异常,即检查异常和非检查异常。但调用给定方法的方法必须仅处理已检查的异常。处理未经检查的异常是可选的。
//可以跳过对未检查异常的处理 public class JavaExample { public static void main(String[] args) { try { //Can skip handling of NullPointerException (unchecked exception) method(); } catch (FileNotFoundException e) { e.printStackTrace(); } } public static void method() throws NullPointerException, FileNotFoundException { //code } }
3. Java中的throw和throws的区别
- throw关键字用于从任何方法或构造函数显式抛出单个异常,而throws关键字用于方法和构造函数声明中,表示该方法可能抛出哪个异常。
throw
后面是异常类的实例,而throws
后面是异常类名称。throw
在方法和构造函数中使用,其中 asthrows
与方法和构造函数签名一起使用。- 我们
throw
只能使用 throw 来声明单个异常,但我们可以使用throws
其中一个可能会或可能不会通过方法抛出的异常来声明多个异常。 - 检查的异常会传播到调用者方法,而未检查的异常则不会传播,因此可能不需要显式的异常处理。
- 使用throw关键字,我们还可以在不使用Break关键字的情况下中断switch 语句或循环,而使用 throws 无法执行这些操作。