为什么在调用一个函数时“抛出exception”是必要的?
class throwseg1 { void show() throws Exception { throw new Exception("my.own.Exception"); } void show2() throws Exception // Why throws is necessary here ? { show(); } void show3() throws Exception // Why throws is necessary here ? { show2(); } public static void main(String s[]) throws Exception // Why throws is necessary here ? { throwseg1 o1 = new throwseg1(); o1.show3(); } }
为什么编译器报告方法show2()
, show3()
和main()
有
未报告的exception必须被捕获或声明被抛出的exception
当我从这些方法中删除throws Exception
?
在Java中,正如您所知,exception可以分为两类:一类需要throws
子句,如果不指定则另一个不能。 现在看下图:
在Java中,您可以抛出任何扩展Throwable
类的东西。 但是,您不需要为所有类指定throws
子句。 具体而言,可以是Error
或RuntimeException
的类或这两者的任何子类。 在你的情况下, Exception
不是Error
或RuntimeException
的子类。 所以,这是一个检查exception,并且必须在throws
子句中指定,如果你不处理那个特定的exception。 这就是为什么你需要throws
条款。
从Java教程 :
一个例外是在程序执行过程中发生的一个事件,它会中断程序指令的正常stream程。
现在,如你所知,例外情况分为两类:选中状态和未选中状态。 为什么这些分类?
检查exception:它们用于表示在执行程序期间可以恢复的问题。 他们通常不是程序员的错。 例如,由用户指定的文件不可读,或者没有可用的networking连接等。在所有这些情况下,我们的程序不需要退出,而是可以采取诸如警告用户的动作,或者进入回退机制(如networking不可用时离线工作)等。
未经检查的exception:他们可以再分为两个:错误和运行时exception 。 他们不加限制的一个原因是,他们数量众多,要处理所有这些都会使我们的程序混乱,并降低其清晰度。 另一个原因是:
-
运行时exception:通常由于程序员的错误而发生。 例如,如果除零的
ArithmeticException
发生或发生ArrayIndexOutOfBoundsException
,那是因为我们在编码时不够小心。 它们通常是因为我们程序逻辑中的一些错误 所以在我们的程序进入生产模式之前必须清除它们。 它们没有被检查,因为我们的程序在发生时必须失败,这样程序员才能在开发和testing的时候解决它。 -
错误:错误是通常程序无法恢复的情况。 例如,如果发生
StackOverflowError
,我们的程序不能做太多,比如增加程序的函数调用堆栈的大小。 或者,如果发生OutOfMemoryError
,我们不能增加可用于我们程序的RAM的数量。 在这种情况下,最好退出程序。 这就是为什么他们没有被选中。
有关详细信息请参阅:
- 未经检查的例外 – 争议
- 抓住或指定要求
Java要求您处理或声明所有exception。 如果你没有使用try / catch块处理exception,那么它必须在方法的签名中声明。
例如:
class throwseg1 { void show() throws Exception { throw new Exception(); } }
应该写成:
class throwseg1 { void show() { try { throw new Exception(); } catch(Exception e) { // code to handle the exception } } }
这样你可以摆脱方法声明中的“抛出exception”声明。
Exception
是一个检查的exception类。 因此,任何调用声明它throws Exception
的方法的代码都必须处理或声明它。
throws Exception
声明是一种自动跟踪可能抛出exception的方法的预期但不可避免的原因。 该声明通常是特定于可能引发的exception的types或types,如throws IOException
或throws IOException, MyException
。
我们都已经或将要编写代码,意想不到地停止,并报告由于我们在运行程序之前没有预料到的exception,例如零除或索引越界。 由于这个方法没有预料到错误,所以它们不能被“抓住”并且用try catch子句来处理。 任何毫无戒心的方法用户也不知道这种可能性,他们的scheme也将停止。
当程序员知道某些types的错误可能会发生,但希望在方法之外处理这些exception时,该方法可以向调用方法“抛出”一种或多种types的exception,而不是处理它们。 如果程序员没有声明方法(可能)抛出一个exception(或者Java没有声明它的能力),那么编译器就不知道,这将取决于方法的未来用户了解,捕捉并处理该方法可能抛出的任何exception。 由于程序可以有很多不同的程序编写的方法,因此很难(不可能)跟踪哪些方法可能会抛出exception。
尽pipeJava有能力声明exception,但是仍然可以编写一个未处理和未声明的exception的新方法,Java将编译它,并且可以运行它并希望得到最好的结果。 Java不会让你做的是编译你的新方法,如果它使用了一个被声明为抛出exception的方法,除非你在你的方法中处理声明的exception,或者声明你的方法抛出例外情况或者有多个例外情况,你可以处理一些例外情况。
当一个程序员声明这个方法抛出了一个特定types的exception时,它只是一个自动的方法来警告其他程序员使用这个方法可能发生exception。 然后程序员可以决定处理exception或通过声明调用方法传递相同的exception来传递警告。 由于编译器已经被警告,在这个新方法中可能有exception,所以它可以自动检查未来的新方法的调用者是处理exception还是声明它并强制执行一个或另一个exception。
这种types的解决scheme的Error: Unhandled exception type java.io.IOException
是,当编译器报告Error: Unhandled exception type java.io.IOException
它给出了被声明为引发exception的方法的文件和行号。 然后,您可以select简单地通过降压并声明您的方法也“抛出IOException”。 这可以一直执行到主要方法,然后程序停止并向用户报告exception。 但是,最好能够抓住exception并以一种很好的方式处理,例如向用户解释发生了什么以及如何解决这个exception。 当一个方法捕获并处理exception时,不再需要声明exception。 可以这样说,降压就停在那里。