考虑以下代码片段:
public static void main(String [] args) throws IOException
{
....
}
我的假设告诉我:任何异常,无论是arrayOutOfBoundsException
还是IOException
,程序都将终止,因为没有捕获异常(并且抛出的异常不是一般的)。然而,我确实看到人们在方法签名处抛出特定的异常。
我的问题:这样做是多余的吗?(因为任何异常都会导致程序终止)
如果它不是多余的,人们这样做的原因是什么?
什么捕获main
方法抛出的异常?
程序将被终止,因为没有捕获异常
看起来可能是这样,因为main
方法是程序开始的地方。但实际上,Java虚拟机(JVM)调用main
方法,因此从技术上讲,它捕获并处理由它抛出的任何异常。
JVM所做的处理只是打印错误流中异常的堆栈跟踪,然后终止程序*。这就是为什么在程序终止之前,您可以在控制台中看到堆栈跟踪(除非错误流被重定向到其他地方,如文件)。
*如果JVM中没有运行其他程序(例如活动的非守护线程),它也会终止自己。
为什么要声明它?
首先,我应该澄清,通过编写然而,我确实看到有人在方法签名中抛出特定的异常。这样做是多余的吗?(因为任何异常都会导致程序终止)
throws
,程序员是而不是抛出异常。程序员只是声明该异常可能由方法抛出,并且方法的调用者必须以某种方式处理。
举个例子:
public static void main(String [] args) throws IOException
这很可能是程序员添加的,因为他的程序从另一个类调用了一些方法,这些方法也声明了This。一些常见的例子是:
public FileWriter(String fileName) throws IOException // a constructor can also throw exceptions
FileWriter.write(int c) throws IOException
这个FileWriter
类的设计者强制它的用户(程序员)处理IOException
。这称为检查异常。
两种类型的异常
检查异常告诉用户,在程序运行期间,导致此异常的场景很可能发生,尽管通常不应该发生(因为我们不是生活在一个理想的世界中)。这表明存在环境错误,即使在最好的程序中也可能抛出此类异常。另一种异常类型是未检查异常。不使用throws
声明NullPointerException
(一个未检查的异常)的原因是,在正常的程序运行期间,不希望出现导致它的场景。如果出现这种情况,这表明存在编程错误和编写不良的程序。
如何处理异常?
有两种方法可以处理方法中收到的异常。
首先是程序员在您的示例中使用的方法。只需将该异常抛出给调用者。
第二种方法是使用try-catch
块在内部处理它:
public static void main (String [] args) // no need to declare "throws IOException"
{
try {
/* some code here that may throw IOException */
} catch (IOException ioe) {
System.err.println("Uhhhh something went wrong!");
// or some logging can happen
ioe.printStackTrace();
System.exit(-6); // a custom error signal can be sent in termination
}
}
为什么呢?
如果它不是冗余的,那么人们这样做的原因是什么?
他们这样做是因为Java强制显式处理已检查异常,而未检查异常可以不处理。
正如我已经解释了处理异常的两种方式,应该注意的是程序员可以根据情况选择一种方法而不是另一种方法。对于某些方法,将捕获的异常抛出给调用者可能更有意义,而对于其他方法,在内部处理捕获的异常可能更有意义。
还有一些懒惰的程序员,他们只是用throws
声明每个检查异常。
检查异常和未检查异常都可以使用上述两种方法中的任何一种来处理。未检查异常为您提供了不处理异常的第三种选择,这反过来又为调用者提供了处理或不处理异常的选择。
如果你使用throws
声明一个未检查异常,它将成为你的方法调用者的检查异常。
你也可以混合和匹配这两种方式。例如,您可以在方法中的任何点内部处理检查异常,即使它被声明为在方法签名中抛出。throws
声明只在未内部处理检查异常的情况下生效。
类的main
方法可以像程序中任何其他常规静态方法一样调用,只需传入一个String
参数数组。它的特殊之处在于,当类作为Java程序启动时,JVM调用该方法。当您手动调用main
方法时,您必须处理可能抛出的检查异常。
如果main
中的某些代码抛出检查异常(如IOException
),则必须在throws
中声明它。在这方面,main
方法就像一个普通方法(实际上,在所有方面,它就像一个普通方法,除了它也是程序的入口点)。