繁体   English   中英

当方法永远不会抛出异常时,为什么编译器允许抛出

[英]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抛出IOExceptionmethodA将停止通过编译。

第二个例子:

假设您有使用methodB代码:

private static void methodA() {
    try {
        methodB(); // throws IOException
    }
    catch (IOException ex) {

    }
}

如果去掉throws从未来版本的条款methodBmethodA将不再通过编译。

methodAprivate ,这个例子不是很有趣,因为它只能在本地使用(在同一个类中,很容易修改调用它的所有方法)。

但是,如果它变为public ,则您不知道谁使用(或将使用)您的方法,因此您无法控制因添加或删除throws子句而可能中断的所有代码。

如果它是一个实例方法,即使你不抛出异常,也允许throws子句的另一个原因 - 可以重写该方法,并且即使基类实现没有,重写方法也可能抛出异常。

因为签名定义了方法的契约。 即使该方法现在不抛出IOException,也许它将来会发生,并且您希望为这种可能性做好准备。

假设您现在只为该方法提供一个虚拟实现,但是您知道,稍后,实际实现可能会抛出IOException。 如果编译器阻止您添加此throws子句,则在提供方法的实际实现后,您将被强制重做所有对该方法的调用(递归)。

关键字throws告诉程序员可能在方法中发生IOException。 现在,如果你没有指定try / catch,则意味着当抛出异常时,程序将停止工作,而在try / catch中,如果抛出异常则通过执行其他操作来处理它。

使用throws可读性并指定异常的可能性,并使用try / catch告诉程序在异常的情况下该怎么做。

  1. 方法B抛出IOException,因此调用methodB的方法负责捕获将由methodB抛出的异常。 尝试从其他方法调用methodB,它会要求您捕获它或重新抛出IOException。 在某个地方你必须捕获链中的IOException(在try / catch块中)。 所以你不会得到编译时错误

    private void sampleMethod(){try {methodB(); } catch(IOException e){// TODO自动生成的catch块e.printStackTrace(); }}

  2. 方法A中的try / catch确实吞下了异常,这意味着methodA负责在try / catch块中捕获异常。 任何java程序中的每个语句都必须是可访问的,即每个语句必须至少可执行一次 ”因此,您将遇到编译器错误,因为您的try块没有任何代码导致IOException。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM