![](/img/trans.png)
[英]Why does the Java compiler allow exceptions to be listed in the throws section that it is impossible for the method to throw
[英]Why does the compiler allow throws when the method will never throw the Exception
我想知道为什么java编译器允许在方法永远不会抛出异常时抛出方法声明。 因为“throws”是一种处理异常的方式(告诉调用者处理它)。
由于有两种处理异常的方法(throws和try / catch)。 在try / catch中,它不允许捕获未在try块中抛出的异常,但它允许抛出一个不会抛出异常的方法。
private static void methodA() {
try {
// Do something
// No IO operation here
} catch (IOException ex) { //This line does not compile because
//exception is never thrown from try
// Handle
}
}
private static void methodB() throws IOException { //Why does this //compile when excetion is never thrown in function body
//Do Something
//No IO operation
}
throws
子句是方法契约的一部分。 它要求方法的调用者表现得好像方法可能抛出指定的异常(即捕获异常或声明自己的throws
子句)。
方法的初始版本可能不会抛出throws
子句中指定的throws
,但未来的版本可以在不破坏API的情况下抛出它(即调用该方法的任何现有代码仍将通过编译)。
相反它也是可能的。 如果该方法用于抛出throws
子句中指定的throws
,但其未来版本不再抛出它,则应保留throws
子句,以免破坏使用您的方法的现有代码。
第一个例子:
假设您有使用methodB
代码:
private static void methodA() {
methodB(); // doesn't have throws IOException clause yet
}
如果以后要更改methodB
抛出IOException
, methodA
将停止通过编译。
第二个例子:
假设您有使用methodB
代码:
private static void methodA() {
try {
methodB(); // throws IOException
}
catch (IOException ex) {
}
}
如果去掉throws
从未来版本的条款methodB
, methodA
将不再通过编译。
当methodA
是private
,这个例子不是很有趣,因为它只能在本地使用(在同一个类中,很容易修改调用它的所有方法)。
但是,如果它变为public
,则您不知道谁使用(或将使用)您的方法,因此您无法控制因添加或删除throws
子句而可能中断的所有代码。
如果它是一个实例方法,即使你不抛出异常,也允许throws
子句的另一个原因 - 可以重写该方法,并且即使基类实现没有,重写方法也可能抛出异常。
因为签名定义了方法的契约。 即使该方法现在不抛出IOException,也许它将来会发生,并且您希望为这种可能性做好准备。
假设您现在只为该方法提供一个虚拟实现,但是您知道,稍后,实际实现可能会抛出IOException。 如果编译器阻止您添加此throws子句,则在提供方法的实际实现后,您将被强制重做所有对该方法的调用(递归)。
关键字throws告诉程序员可能在方法中发生IOException。 现在,如果你没有指定try / catch,则意味着当抛出异常时,程序将停止工作,而在try / catch中,如果抛出异常则通过执行其他操作来处理它。
使用throws可读性并指定异常的可能性,并使用try / catch告诉程序在异常的情况下该怎么做。
方法B抛出IOException,因此调用methodB的方法负责捕获将由methodB抛出的异常。 尝试从其他方法调用methodB,它会要求您捕获它或重新抛出IOException。 在某个地方你必须捕获链中的IOException(在try / catch块中)。 所以你不会得到编译时错误 。
private void sampleMethod(){try {methodB(); } catch(IOException e){// TODO自动生成的catch块e.printStackTrace(); }}
方法A中的try / catch确实吞下了异常,这意味着methodA负责在try / catch块中捕获异常。 “ 任何java程序中的每个语句都必须是可访问的,即每个语句必须至少可执行一次 ”因此,您将遇到编译器错误,因为您的try块没有任何代码导致IOException。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.